پروپینسٹی اسکورز کا استعمال کرتے ہوئے پروڈکٹ کا تجربہ: ازگر میں ایل ایل ایم پر مبنی خصوصیات کے لیے کازل انفرنس۔

LLM پر مبنی خصوصیات پر کارآمد نتیجہ چلانے والی کوئی بھی مصنوعات کی تجرباتی ٹیم بالآخر اسی دیوار سے ٹکرائے گی۔ جب کوئی صارف "AI اسسٹنٹ کو آزمائیں” پر کلک کرتا ہے، تو رضاکار بے ترتیب نمونہ نہیں ہوتے ہیں۔

آپ کے پروڈکٹ نے پچھلی سہ ماہی میں ایک نیا ایجنٹ موڈ لانچ کیا۔ اسے فعال کرنے کے لیے، صارفین کو ‘ایجنٹ موڈ آزمائیں’ ٹوگل پر ٹیپ کرنا چاہیے۔ ڈیش بورڈ نمبرز حیرت انگیز ہیں۔ ایجنٹ موڈ کے صارفین غیر استعمال کنندگان کے مقابلے میں 21 فیصد پوائنٹس زیادہ کام مکمل کرتے ہیں۔ CPO اسے سال کا بہترین فیچر لانچ قرار دیتا ہے۔

لیکن میں جانتا ہوں کہ کچھ غلط ہے۔ انتہائی مصروفیت رکھنے والے صارفین مسلسل نئی خصوصیات حاصل کرتے ہیں، جبکہ کم مصروف صارفین ٹوگلز کو مکمل طور پر نظر انداز کرتے ہیں۔ 21 نکاتی فرق ایجنٹ کی تاثیر کی پیمائش کرتا ہے جو بجلی استعمال کرنے والوں اور باقیوں کے درمیان موجودہ فرق کے ساتھ مل کر ہے۔

یہ ایک آپٹ ان ٹریپ ہے۔ یہ کسی بھی تخلیقی AI پروڈکٹ میں ظاہر ہوگا جو صارف کے زیر کنٹرول ٹوگل کے پیچھے فعالیت فراہم کرتا ہے۔ "AI اسسٹنٹ کو آزمائیں”، "سمارٹ جواب کو فعال کریں”، "کوڈ کی تجاویز کو آن کریں”۔ وہ صارفین جو منتخب کرنے کے لیے کلک کرتے ہیں وہ ماضی میں اسکرول کرنے والے صارفین سے منظم طریقے سے مختلف ہوتے ہیں۔ دو گروہوں کے درمیان ایک سادہ موازنہ کسی خصوصیت کے کارآمد اثر کو کم کرتا ہے جس نے صارف کو پہلی جگہ انتخاب کرنے پر اکسایا۔

ٹوگلز کے پیچھے AI خصوصیات کو چلانا ایک پروڈکٹ کا تجربہ ہے۔ مفروضہ: یہ خصوصیت ان صارفین کے نتائج کو بہتر بناتی ہے جو اسے اپناتے ہیں۔

A/B ٹیسٹنگ کے برعکس، جو ایک سکے کو پلٹ کر دو غیر مساوی آبادی پیدا کرتا ہے، ایک ٹوگل انتخاب کرنے سے پہلے دو مختلف آبادیوں کو تخلیق کرتا ہے۔ موجودہ اختلافات پیمائش کا مسئلہ ہیں اور ڈیش بورڈ نمبرز پر ٹی ٹیسٹ کے ذریعے حل نہیں کیا جا سکتا۔

پروپینسٹی سکور کا طریقہ ایک شماریاتی ٹول ہے جسے ڈیٹا سائنسدان اپنانے کے تعصب کو کسی خصوصیت کی حقیقی تاثیر سے الگ کرنے کے لیے استعمال کرتے ہیں۔ موازنہ کو دوبارہ وزن دیا جاتا ہے (یا دوبارہ ملایا جاتا ہے) تاکہ منتخب اور غیر منتخب گروپوں کا موازنہ قابل مشاہدہ خصوصیات پر کیا جا سکے، جیسا کہ بے ترتیب تجربہ فراہم کرتا ہے۔

یہ ٹیوٹوریل آپ کو 50,000 صارفین کے مصنوعی SaaS ڈیٹاسیٹ پر پوری پائپ لائن (متوقع تخمینہ، الٹا امکانی وزن، قریب ترین پڑوسی مماثلت، توازن کی تشخیص، اور بوٹسٹریپ اعتماد کے وقفوں) کے بارے میں معلوم زمینی سچائی کازل اثرات کے ساتھ لے کر جاتا ہے۔ آپ اس کا اندازہ لگائیں گے، غیر یقینی صورتحال کا اندازہ لگائیں گے، اور دیکھیں گے کہ آپ کا نقطہ نظر خاموشی سے کہاں ٹوٹتا ہے۔

ساتھی کوڈ: تمام کوڈ بلاکس ساتھی نوٹ بک میں github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm/tree/main/02_propensity_opt_in پر اینڈ ٹو اینڈ چلائے جاتے ہیں۔ لیپ ٹاپ (psm_demo.ipynb) میں تمام آؤٹ پٹ پری رن ہے، لہذا آپ اسے مقامی طور پر چلانے سے پہلے GitHub سے پڑھ سکتے ہیں۔

انڈیکس

کیوں آپٹ ان بے ہودہ موازنہ کو توڑ دیتا ہے۔

A/B ٹیسٹنگ کی ریاضی ایک مفروضے کی وجہ سے خوبصورت ہے: علاج ہر چیز سے آزادانہ طور پر تفویض کیا جاتا ہے۔ سکے پلٹائیں: آدھے صارفین ایجنٹ موڈ استعمال کرتے ہیں، سکے کا پلٹنا کسی بھی الجھن کو توڑ دیتا ہے جو کنفیگریشن کی وجہ سے ہو سکتا ہے۔ آپٹ ان دنیا میں کوئی سکے نہیں ہیں۔

تین طریقہ کار انتخاب کے موازنہ کو گمراہ کن بناتے ہیں۔

1. شرکت کے بارے میں انتخاب

پاور صارفین ہر چیز پر کلک کرتے ہیں۔ اگر آپ کا انتہائی مصروف گروپ 65% وقت ایجنٹ موڈ کا انتخاب کرتا ہے اور آپ کا کم مصروف گروپ اسے 12% وقت کا انتخاب کرتا ہے، تو آپ نے اپنے منتخب گروپ کو صارفین کے ساتھ اسٹیک کیا ہے جو بہرحال زیادہ کام کریں گے۔

یہ ساختی عدم توازن خود ایجنٹ کے اپنے عمل کو انجام دینے سے پہلے زیادہ تر مشاہدہ شدہ لفٹ کی وضاحت کرتا ہے۔

2. نیت پر مبنی انتخاب

وہ صارفین جو نئی خصوصیات کا انتخاب کرتے ہیں ان کے ذہن میں استعمال کے مخصوص معاملات ہوتے ہیں۔ "کوڈ کی تجاویز آزمائیں” پر کلک کرنے والے ڈویلپرز کے پاس لکھنے کے لیے کوڈ پہلے سے موجود ہوتا ہے۔ ان صارفین نے کنٹرول UI کے ساتھ بھی اپنے کاموں کو زیادہ شرح پر مکمل کیا ہوگا۔

3. اپنی خطرے کی برداشت کا انتخاب کریں۔

ابتدائی گود لینے والے کھردرے کناروں کو برداشت کر سکتے ہیں۔ وہ صارفین جو ‘بیٹا کو آزمائیں’ پر کلک کرتے ہیں اور کم تاخیر سے قیام دیکھتے ہیں، جبکہ خطرے سے بچنے والے صارفین منتیں کرتے ہیں۔

آپ کا منتخب گروپ ان لوگوں کے لیے افزودہ ہے جو ایک خراب تجربہ کے ساتھ پیش کرنا چاہتے ہیں جو آپ کی پیمائش کر سکتے ہیں ہر بہاؤ میٹرک کو متاثر کرتا ہے۔

تینوں ایک جیسی علامات کا سبب بنتے ہیں۔ یعنی، دوسرے تمام صارفین کے ساتھ ایک خام موازنہ، جو کسی خصوصیت کے کارآمد اثر کو 2 یا اس سے زیادہ کے عنصر سے بڑھا سکتا ہے، اس بات پر منحصر ہے کہ سب سے زیادہ صارفین کے درمیان انتخاب کتنا مرتکز ہے۔

اس ٹیوٹوریل میں سیٹ مصنوعی ڈیٹا پر، ایک سادہ موازنہ حقیقی +8pp اثر کو +21pp (2.6x اوور شوٹ) تک بڑھاتا ہے۔ اس کو درست کرنے کے لیے پروپینسیٹی سکور کے طریقے موجود ہیں۔

پروپینسٹی اسکورز دراصل کیا کرتے ہیں۔

شکل 1: دو فرضی گروہوں کے لیے اسکیمیٹک رجحان سکور کی تقسیم۔ منتخب گروپ (سرخ) کو اعلی رجحانات کی طرف جھکا دیا گیا ہے، جبکہ غیر منتخب گروپ (نیلے) کو کم رجحانات کی طرف جھکا دیا گیا ہے۔

اوپر دی گئی تصویر میں، x-axis کے نیچے قوسین کی پٹی اسکور کی حد کو تین حصوں میں تقسیم کرتی ہے۔ یعنی، ایک کم پروپینسیٹی کنٹرول-بھاری علاقہ جس میں کچھ علاج کیے گئے صارفین ہوں، ایک مرکزی مشترکہ سپورٹ ایریا جہاں دونوں گروپوں کی اچھی نمائندگی کی گئی ہو، اور کچھ کنٹرولز کے ساتھ ایک اعلی پروپینسیٹی ٹریٹمنٹ ہیوی ایریا۔ پروپینسٹی سکور کے طریقے ری ویٹنگ یا ری سیٹمیٹری کے ذریعے سپورٹ کے ایک مشترکہ علاقے میں کام کرتے ہیں اس طرح کہ دونوں گروپ قابل مشاہدہ پر متوازن نظر آتے ہیں۔ احتیاط کے ساتھ انتہائی حصوں کو کاٹیں یا ہینڈل کریں۔

رجحان سکور وہ امکان ہے کہ صارف قابل مشاہدہ خصوصیات کے پیش نظر کسی چیز کا انتخاب کرے گا۔ ہم اس امکان کا ایک اچھا اندازہ لگا سکتے ہیں اور نمونے کو دوبارہ وزن دینے کے لیے اس کا استعمال کر سکتے ہیں تاکہ منتخب اور غیر منتخب صارفین مشاہدات میں ایک جیسے نظر آئیں۔ یہ ایسے ہی ہے جیسے انتخاب بے ترتیب تھے۔

رجحان کے اسکور استعمال کرنے کے لیے دو عملی حکمت عملی یہ ہیں:

  • الٹا امکانی وزن (IPW) ہر صارف کو ایک وزن تفویض کیا جاتا ہے جو اسے درحقیقت حاصل کردہ علاج حاصل کرنے کے امکان کے الٹا کے برابر ہوتا ہے۔ منتخب صارفین کا وزن 1/P ہے (منتخب شدہ)۔ غیر آپٹ ان صارفین کا وزن 1/P ہے (کوئی آپٹ ان نہیں)۔ وزن کے بعد، دونوں گروہوں کو قابل مشاہدہ کرنے پر متوازن کیا جاتا ہے، اور نتائج میں وزنی فرق اوسط علاج کے اثر کا تخمینہ لگاتا ہے۔

  • ملاپ ہم ہر آپٹ ان صارف کو ایک یا زیادہ غیر منتخب کردہ صارفین کے ساتھ ملتے ہیں جس کے اسی طرح کے رجحان سکور ہوتے ہیں۔ مماثل جوڑوں کے درمیان نتائج کا اوسط فرق علاج کے ہدف (ATT) پر علاج کے اوسط اثر کا تخمینہ لگاتا ہے، یعنی اصل میں رضامندی کے صارفین سے حاصل ہونے والا نتیجہ۔

دونوں طریقے تین شناختی مفروضوں پر مبنی ہیں جو ایک ساتھ کام کرتے ہیں۔

  1. سب سے پہلے مبہم نہیں: تمام قابل مشاہدہ متغیرات جو انتخاب کو آگے بڑھاتے ہیں اور نتائج کو متاثر کرتے ہیں رجحان ماڈل میں ہیں۔

  2. دوسرا ایک دوسرے پر رکھو (جسے مثبتیت بھی کہا جاتا ہے): ہر صارف کے پاس آپٹ ان کرنے کا غیر صفر امکان ہوتا ہے اور آپٹ آؤٹ کرنے کا غیر صفر امکان ہوتا ہے۔

  3. تیسرا کوئی مداخلت نہیں۔: ایک صارف کے انتخاب کا فیصلہ دوسرے صارف کے نتائج (مستحکم یونٹ ٹریٹمنٹ ویلیو مفروضہ، یعنی SUTVA) کو متاثر نہیں کرتا ہے۔

ان میں سے ایک کی خلاف ورزی تخمینہ کی طرفداری کرے گی چاہے باقی دو کے پاس ہوں۔ اس ٹیوٹوریل کے آخر میں ناکامی کے طریقے ہر موڈ میں آپ کی رہنمائی کرتے ہیں۔

شرطیں

Python 3.11 یا اس سے زیادہ، پانڈوں اور سکِٹ لرن سے واقفیت، اور لاجسٹک ریگریشن کے بارے میں قطعی معلومات کی ضرورت ہے۔

اس ٹیوٹوریل کے لیے پیکجز انسٹال کریں۔

pip install numpy pandas scikit-learn matplotlib

موجودہ صورتحال کچھ یوں ہے: چار پیکج پوری پائپ لائن کا احاطہ کرتے ہیں۔ پانڈاس ڈیٹا کو لوڈ کرتا ہے، NumPy وزن اور سرنی ریاضی کو ہینڈل کرتا ہے، scikit-learn propensity ماڈل میں فٹ بیٹھتا ہے اور قریب ترین پڑوسی میچنگ کرتا ہے، اور matplotlib بے کار تشخیص پیش کرتا ہے۔

مصنوعی ڈیٹاسیٹ حاصل کرنے کے لیے، ساتھی ریپوزٹری کو کلون کریں۔

git clone https://github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm.git
cd product-experimentation-causal-inference-genai-llm
python data/generate_data.py --seed 42 --n-users 50000 --out data/synthetic_llm_logs.csv

موجودہ صورتحال کچھ یوں ہے: کلون ساتھی ذخیرہ درآمد کرتا ہے اور generate_data.py ایک مشترکہ مصنوعی ڈیٹاسیٹ تخلیق کرتا ہے جو پوری سیریز میں استعمال ہوتا ہے۔ سیڈ 42 ڈیٹاسیٹ کو دوبارہ پیدا کرنے کے قابل رکھتا ہے اور 50,000 صارفین اس ٹیوٹوریل میں تمام تخمینوں کے لیے واضح سگنل فراہم کرتے ہیں۔ آؤٹ پٹ CSV اس پر پہنچے گا: data/synthetic_llm_logs.csv.

ورکنگ مثال سیٹ اپ

مصنوعی ڈیٹاسیٹ SaaS پروڈکٹ کی نقل کرتا ہے جہاں صارف ایک ایجنٹ موڈ کا انتخاب کر سکتے ہیں جو زیادہ مہنگا ماڈل استعمال کرتا ہے۔ اگر آپ کے 50,000 صارفین ہیں، تو آپ کی منگنی کی شرح منگنی کے مرحلے کے لحاظ سے بہت مختلف ہوگی۔ بھاری صارفین 65%، درمیانے صارفین 35%، اور ہلکے صارفین 12% پر انتخاب کرتے ہیں۔

ڈیٹا جنریٹر میں ظاہر ہونے والا اصل کازل اثر منتخب صارف کے لیے کام کی تکمیل پر +8 فیصد پوائنٹس ہے۔ ایک سادہ موازنہ میں، انتخابی تعصب اسے تقریباً +21 فیصد پوائنٹس تک بڑھاتا ہے کیونکہ یہ منتخب گروپ کو سب سے زیادہ مصروف صارفین کے ساتھ اسٹیک کرتا ہے۔

اصل حقائق کو جاننا ہمیں یہ دیکھنے کی اجازت دیتا ہے کہ آیا پروپینسیٹی سکور کا طریقہ انہیں بحال کرتا ہے۔

اپنا ڈیٹا لوڈ کریں اور انتخاب کے مسائل کی جانچ کریں۔

import pandas as pd

df = pd.read_csv("data/synthetic_llm_logs.csv")

print(df.groupby("engagement_tier").opt_in_agent_mode.mean().round(3))

naive_effect = (
    df[df.opt_in_agent_mode == 1].task_completed.mean()
    - df[df.opt_in_agent_mode == 0].task_completed.mean()
)
print(f"nNaive opt-in effect: {naive_effect:+.4f}")

متوقع پیداوار:

engagement_tier
heavy     0.647
light     0.120
medium    0.353
Name: opt_in_agent_mode, dtype: float64

Naive opt-in effect: +0.2106

موجودہ صورتحال کچھ یوں ہے: 50,000 قطاریں لوڈ کریں، انہیں شرکت کے درجے کے مطابق گروپ کریں، اور ہر گروپ میں انتخاب کا فیصد پرنٹ کریں۔ بھاری صارفین کے پاس ہلکے صارفین کے مقابلے میں بہت زیادہ انتخاب ہوتے ہیں۔ مشغول ہونے پر یہ انتخاب کا ایک نمونہ ہے جو ڈیٹا میں ظاہر ہوتا ہے۔ سادہ اثر +0.2106 (21 فیصد پوائنٹس) تک پہنچ جاتا ہے، جو +0.08 کی اصل قیمت سے تقریباً تین گنا زیادہ ہے۔ یہ فرق بالکل وہی ہیں جن کو ختم کرنے کے لیے پروپینسیٹی سکور کے طریقے ہیں۔

مرحلہ 1: پروپینسٹی سکور کا تخمینہ

رجحان سکور ایک ماڈل کا آؤٹ پٹ ہے جو قابل مشاہدہ خصوصیات سے آپٹ ان کی پیش گوئی کرتا ہے۔ لاجسٹک ریگریشن ایک اچھا نقطہ آغاز ہے کیونکہ یہ قابل تشریح اور تیز ہے، لیکن مرحلہ 4 میں بیلنس کی تشخیص کو دیکھیں۔ اگر وزنی SMD 0.1 سے اوپر رہتا ہے، تو لاجسٹک ماڈل میں تعاملات غائب ہیں اور گریڈینٹ بوسٹنگ اگلی کارروائی ہے۔

اس ڈیٹاسیٹ کے لیے، متعلقہ مشاہدات میں شرکت کا درجہ بندی اور استفسار کا اعتماد ہے۔ اصل پروڈکٹ میں وہ تمام متغیرات شامل ہیں جن کے بارے میں سوچا گیا تھا کہ آپٹ ان ڈرائیو کریں، بشمول ڈیوائس کی قسم، استعمال کی مدت، پلان ٹائر، اور استعمال کے ماضی کے نمونے۔

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score

X = pd.get_dummies(
    df[["engagement_tier", "query_confidence"]],
    drop_first=True
).astype(float)
y_treat = df.opt_in_agent_mode

ps_model = LogisticRegression(max_iter=1000).fit(X, y_treat)
df["propensity"] = ps_model.predict_proba(X)[:, 1]

# Basic sanity checks
print(df.groupby("engagement_tier").propensity.mean().round(3))
print(
    f"nPropensity range (treated):  "
    f"{df[df.opt_in_agent_mode == 1].propensity.min():.3f} - "
    f"{df[df.opt_in_agent_mode == 1].propensity.max():.3f}"
)
print(
    f"Propensity range (control):  "
    f"{df[df.opt_in_agent_mode == 0].propensity.min():.3f} - "
    f"{df[df.opt_in_agent_mode == 0].propensity.max():.3f}"
)
print(f"Propensity model AUC: {roc_auc_score(y_treat, df.propensity):.3f}")

متوقع پیداوار:

engagement_tier
heavy     0.646
light     0.120
medium    0.353
Name: propensity, dtype: float64

Propensity range (treated):  0.114 - 0.675
Propensity range (control):  0.114 - 0.673
Propensity model AUC: 0.744

موجودہ صورتحال کچھ یوں ہے: یہ شرکت کی پرت کو ایک ڈمی متغیر کے طور پر انکوڈ کرتا ہے، استفسار کے اعتماد کو مستقل بناتا ہے، اور لاجسٹک ریگریشن ماڈل میں فٹ بیٹھتا ہے۔ ماڈل سے متوقع امکان ہر صارف کا رجحان سکور ہے۔

سیکھنا LogisticRegression L2 ریگولرائزیشن کو بطور ڈیفالٹ لاگو کریں (C=1.0)، جو رجحان کو 0.5 کی طرف تھوڑا سا سکڑتا ہے۔ آپ اسے پیداوار کے استعمال کے لیے ترتیب دے سکتے ہیں۔ penalty=None اگر آپ فاسد فٹ چاہتے ہیں۔

ماڈل کو کیلیبریٹ کیا گیا ہے تاکہ ہر شرکت کی سطح کے اندر اوسط رجحان اس درجہ کے لئے اصل آپٹ ان کی شرح کو تقریبا بالکل ٹھیک کر لے۔ 0.744 کا AUC اس بات کی تصدیق کرتا ہے کہ ماڈل آپٹ انز اور نان آپٹ انز کے درمیان بہت زیادہ موقع (0.5) میں فرق کرتا ہے۔

اور علاج اور کنٹرول گروپس (دونوں کی حد تقریباً 0.11 سے 0.67 تک) کے درمیان رجحان کی حد اوورلیپ ہوتی ہے، بصری اوورلیپ پر مشروط۔

50,000 حقیقی صارفین کے ساتھ مصنوعی ڈیٹاسیٹ پر ایک ہی مثبت ٹیسٹ کے دو خیالات۔

شکل 2: 50,000 حقیقی صارفین کے ساتھ مصنوعی ڈیٹاسیٹ پر ایک ہی مثبت ٹیسٹ کے دو خیالات۔

اوپر دی گئی تصویر میں، اوپر والا پینل ہر گروپ کے لیے فٹڈ پرینسٹی سکور کے ہموار کرنل کثافت کے منحنی خطوط دکھاتا ہے۔ جیسا کہ توقع کی گئی ہے، تین چوٹیاں شرکت کے تین درجوں سے مساوی ہیں: p ≒ 0.12 پر ہلکی، p ≒ 0.35 پر درمیانی، اور p ≒ 0.65 پر بھاری۔ کیونکہ آپٹ ان کی شرح کا تعین درجے کے لحاظ سے ہوتا ہے۔ نیچے والا پینل اسی تقسیم کو خام شمار فی پرت میں تبدیل کرتا ہے۔ ہر درجے میں ہزاروں صارفین ہوتے ہیں، آپٹ اِن اور آپٹ اِن دونوں، بالکل وہی جو مثبتیت کی ضرورت ہے۔

اگر شکل 1 اسکیمیٹک طور پر خیال کو واضح کرتا ہے، تو یہ ظاہر کرتا ہے کہ اس کا اطلاق ڈیٹا پر ہوتا ہے، تاکہ درج ذیل وزن اور مماثلت اصل متضاد کو استعمال کر سکے۔

مرحلہ 2: الٹا امکانی وزن

IPW ہر صارف کے رجحانات کے الٹے تناسب میں وزن تفویض کرتا ہے۔ 0.12 کے رجحان کے ساتھ آپٹ ان صارفین نایاب ہیں (ہلکے صارف جو کم مصروفیت کے باوجود آپٹ ان کرتے ہیں) اور آبادی میں 1/0.12 ≒ 8 ملتے جلتے صارفین کے بارے میں معلومات فراہم کرتے ہیں۔ 0.12 کے رجحان کے ساتھ کنٹرول صارف ایک ہلکے صارف کے لئے متوقع کیس ہے جو باہر رہتا ہے، لہذا یہ عام ہے اور اس کا وزن 1/(1 – 0.12) ≒ 1.14 ہوتا ہے۔

import numpy as np

# ATE weights: 1/P(treat) for treated, 1/P(no treat) for control
df["ipw"] = np.where(
    df.opt_in_agent_mode == 1,
    1 / df.propensity,
    1 / (1 - df.propensity)
)

t = df[df.opt_in_agent_mode == 1]
c = df[df.opt_in_agent_mode == 0]
ate_ipw = (
    (t.task_completed * t.ipw).sum() / t.ipw.sum()
    - (c.task_completed * c.ipw).sum() / c.ipw.sum()
)
print(f"IPW average treatment effect (ATE): {ate_ipw:+.4f}")

# ATT: what opt-in users actually gained
df["ipw_att"] = np.where(
    df.opt_in_agent_mode == 1,
    1,
    df.propensity / (1 - df.propensity)
)
t = df[df.opt_in_agent_mode == 1]   # re-slice now that ipw_att is in df
c = df[df.opt_in_agent_mode == 0]
treated_mean = t.task_completed.mean()
control_w_mean = (c.task_completed * c.ipw_att).sum() / c.ipw_att.sum()
att_ipw = treated_mean - control_w_mean
print(f"IPW average treatment effect on treated (ATT): {att_ipw:+.4f}")

متوقع پیداوار:

IPW average treatment effect (ATE): +0.0851
IPW average treatment effect on treated (ATT): +0.0770

موجودہ صورتحال کچھ یوں ہے: سب سے پہلے، تمام صارفین کے لیے ATE وزن کا حساب لگائیں اور منتخب اور غیر منتخب گروپوں کے درمیان کام کی تکمیل کے لیے وزن میں فرق حاصل کریں۔ اس کے بعد ہم ATT وزن کا حساب لگاتے ہیں، جو علاج شدہ گروپ کی کوویریٹ تقسیم سے مماثل ہونے کے لیے صرف کنٹرول گروپ کا وزن کرتے ہیں، اور علاج کیے گئے گروپ کے لیے علاج کے اوسط اثر کا حساب لگاتے ہیں۔

ATE آبادی کے سوالات کا جواب دیتا ہے۔ بے ترتیب صارفین کے لیے کیا مضمرات ہیں جنہوں نے بہرحال انتخاب کیا ہو یا نہ کیا ہو؟ ATT صارف کے سوالات کا جواب دیتا ہے جیسے: آپٹ ان صارفین کو واقعی کیا ملا؟ اس ڈیٹاسیٹ میں، ATE +0.0851 تک پہنچ جاتا ہے اور ATT +0.0770 تک پہنچ جاتا ہے۔ دونوں حقیقی +0.08 کے قریب ہیں اور بولی +0.2106 کے مقابلے میں بہت بڑی بہتری ہے۔

عملی طور پر، فرق اہم ہے. اس بات کا تعین کرتا ہے کہ آیا اس خصوصیت کو ان صارفین کے لیے جاری کرنا ہے جنہوں نے ATE کو کال کرنے کا انتخاب نہیں کیا ہے۔ آپٹ ان صارفین کے ذریعہ ATT کرنسی میں کیپچر کی گئی قدر پر رپورٹس۔

مرحلہ 3: قریب ترین پڑوسی میچ

ملاپ ایک مختلف نقطہ نظر لیتا ہے. یعنی، ہم ہر منتخب صارف کو غیر منتخب صارف کے ساتھ قریب ترین رجحان کے اسکور کے ساتھ جوڑا بناتے ہیں اور مماثل جوڑوں کے اوسط نتائج کا فرق لیتے ہیں۔ نتائج کا تخمینہ اے ٹی ٹی ہے۔

from sklearn.neighbors import NearestNeighbors

treated_ps = df[df.opt_in_agent_mode == 1][["propensity"]].values
control_ps = df[df.opt_in_agent_mode == 0][["propensity"]].values

nn = NearestNeighbors(n_neighbors=1).fit(control_ps)
_, idx = nn.kneighbors(treated_ps)

treated_outcomes = df[df.opt_in_agent_mode == 1].task_completed.values
matched_control_outcomes = (
    df[df.opt_in_agent_mode == 0].task_completed.values[idx.flatten()]
)

att_match = (treated_outcomes - matched_control_outcomes).mean()
print(f"1-NN matching ATT: {att_match:+.4f}")

متوقع پیداوار:

1-NN matching ATT: +0.0752

موجودہ صورتحال کچھ یوں ہے: ہم ہر گروپ کے لیے پروپینسیٹی سکور نکالتے ہیں، کنٹرول گروپ کے قریب ترین انڈیکس میں فٹ کرتے ہیں، اور ہر علاج کیے جانے والے صارف کے لیے قریب ترین کنٹرول صارف تلاش کرتے ہیں۔

کہ NearestNeighbors یہ متبادل کے ذریعے مماثلت کا معاملہ ہے، کیونکہ انڈیکس ایک ہی کنٹرول کرنے والے صارف کو متعدد پروسیسنگ صارفین کے لیے میچ کے طور پر منتخب کرنے کی اجازت دیتا ہے۔

ہر پروسیس شدہ صارف اور ان کے مماثل کنٹرول کے نتائج لیں، فی جوڑا فرق تلاش کریں، اور جوڑوں میں اوسط۔ نتائج کا اندازہ لگایا گیا ہے کہ رضامندی دینے والے صارف نے اس سے ملتے جلتے صارف کے مقابلے میں کیا حاصل کیا جس نے رضامندی نہیں دی۔

+0.0752 کا نتیجہ +0.08 کی اصل قیمت کے قریب ہے، لیکن IPW ATT سے قدرے کم ہے۔ یہ ایک عام 1-NN میچ ہے کیونکہ واحد قریبی پڑوسی ایک اعلی تغیر کا تخمینہ لگانے والا ہے۔

دو مختلف قسموں کے بارے میں جاننے کے قابل ہیں۔ فال بیک مماثلت کا استعمال (جو ہم نے ابھی کیا ہے) ایک واحد کنٹرول صارف کو متعدد پروسیس شدہ صارفین کے لیے میچ کے طور پر کام کرنے کی اجازت دیتا ہے، جو تعصب کو کم کرتا ہے لیکن جب اچھے مماثلتوں کی کمی ہوتی ہے تو فرق بڑھ جاتا ہے۔

متبادل کے بغیر میچنگ ہر کنٹرول صارف کو زیادہ سے زیادہ ایک پروسیس شدہ صارف کو تفویض کرتی ہے۔ یہ فرق کو کم رکھتا ہے لیکن جب علاج شدہ گروپ دستیاب کنٹرول کو بونا کرتا ہے تو کم معیار کے جوڑے کو مجبور کرتا ہے۔

زیادہ تر پیداواری تجزیوں کے لیے، k = 3-5 اور k-قریب ترین پڑوسیوں کے مماثل متبادل معقول ڈیفالٹس ہیں۔

مرحلہ 4: کوویریٹ بیلنس چیک کریں۔

پروپینسٹی سکور کے طریقے صرف اس صورت میں کام کرتے ہیں جب آپ گروپوں میں ہم آہنگی کو متوازن کرتے ہیں۔ اگر آپ کا بیلنس کم ہے تو آپ کا تخمینہ غلط ہے اور اسے چیک کیا جانا چاہیے۔

معیاری تشخیص ہر کوویریٹ کے لیے معیاری اوسط فرق (SMD) ہے۔ SMD ٹریٹمنٹ گروپ کے وسط کا موازنہ اسٹینڈرڈ انحراف کے ذریعے تقسیم کردہ کنٹرول مطلب سے کرتا ہے۔

وزن کرنے سے پہلے، SMD ہمیں بتاتا ہے کہ خام گروپ کتنا غیر متوازن ہے۔ وزن کے بعد، یہ چھوٹا ہونا چاہیے (|SMD| <0.1 روایتی معیار ہے)۔

def smd(treated_vals, control_vals, treated_w=None, control_w=None):
    """Standardized mean difference, optionally with weights."""
    if treated_w is None:
        treated_w = np.ones(len(treated_vals))
    if control_w is None:
        control_w = np.ones(len(control_vals))
    t_mean = np.average(treated_vals, weights=treated_w)
    c_mean = np.average(control_vals, weights=control_w)
    pooled_std = np.sqrt((treated_vals.var() + control_vals.var()) / 2)
    return (t_mean - c_mean) / pooled_std

engagement_heavy = (df.engagement_tier == "heavy").astype(float).values
qc = df.query_confidence.values
tr = (df.opt_in_agent_mode == 1).values

covariates = {
    "engagement_tier_heavy": engagement_heavy,
    "query_confidence": qc,
}

print(f"{'Covariate':<30} {'Raw SMD':>10} {'Weighted SMD':>15}")
for name, vals in covariates.items():
    smd_raw = smd(vals[tr], vals[~tr])
    smd_weighted = smd(
        vals[tr], vals[~tr],
        treated_w=df[tr].ipw.values,
        control_w=df[~tr].ipw.values,
    )
    print(f"{name:<30} {smd_raw:>+10.3f} {smd_weighted:>+15.3f}")

متوقع پیداوار:

Covariate                         Raw SMD    Weighted SMD
engagement_tier_heavy              +0.742          +0.002
query_confidence                   -0.032          -0.003

موجودہ صورتحال کچھ یوں ہے: مددگار اختیاری IPW وزن کا استعمال کرتے ہوئے تمام کوویریٹس کے لیے معیاری اوسط فرق کا حساب لگاتا ہے۔

پھر ہم ہر کوویریٹ کے لیے خام اور وزنی SMD پرنٹ کرتے ہیں۔ خام ایس ایم ڈی engagement_tier_heavy یہ +0.742 ہے (جسے بہت سے صارفین سب سے زیادہ منتخب کرتے ہیں) اور وزنی SMD +0.002 تک گر جاتا ہے، جو کہ ایک صاف پاس ہے۔ سوال کا اعتماد پہلے سے ہی خام ڈیٹا میں توازن کے قریب ہے، اور ہم اسے وزن کے ذریعے برقرار رکھتے ہیں۔ اگر وزنی SMD مطلق قدر میں 0.1 سے اوپر واپس آجاتا ہے، تو آپ کے رجحان کے ماڈل میں کچھ کمی ہے۔ لاجسٹک ریگریشن میں ترامیم عام طور پر امیر خصوصیات یا تعامل کی شرائط ہیں۔

اوپر والا شکل 2 اب بصری طور پر اس بات کی تصدیق کرتا ہے کہ SMD نے عددی اعتبار سے کس چیز کی تصدیق کی ہے: کہ سپرپوزیشن کی شرائط برقرار ہیں اور یہ توازن قابل حصول ہے۔

مرحلہ 5: بوٹسٹریپ اعتماد کا وقفہ

نقطہ تخمینہ صرف آدھی کہانی ہے۔ ہر تخمینہ جو آپ پروڈکٹ ٹیم کو رپورٹ کرتے ہیں ایک وقفہ درکار ہوتا ہے جو آپ کو بتاتا ہے کہ +0.08 +0.03 یا +0.12 سے مختلف ہے۔ چونکہ IPW اور مماثلت کے لیے تجزیاتی معیاری غلطیاں تخمینی رجحان کے اسکور کی وجہ سے مشکل ہوتی ہیں، اس لیے سب سے آسان اور ایماندارانہ اقدام ایک نان پیرامیٹرک بوٹسٹریپ ہے۔

def estimate_all(sample):
    """Return (ATE_IPW, ATT_IPW, ATT_match) on a bootstrap sample."""
    s = sample.copy()
    X_s = pd.get_dummies(
        s[["engagement_tier", "query_confidence"]], drop_first=True
    ).astype(float)
    ps = LogisticRegression(max_iter=1000).fit(X_s, s.opt_in_agent_mode)
    s["p"] = ps.predict_proba(X_s)[:, 1]

    s["w_ate"] = np.where(
        s.opt_in_agent_mode == 1, 1 / s.p, 1 / (1 - s.p)
    )
    s["w_att"] = np.where(
        s.opt_in_agent_mode == 1, 1, s.p / (1 - s.p)
    )
    t, c = s[s.opt_in_agent_mode == 1], s[s.opt_in_agent_mode == 0]

    ate = (
        (t.task_completed * t.w_ate).sum() / t.w_ate.sum()
        - (c.task_completed * c.w_ate).sum() / c.w_ate.sum()
    )
    att = t.task_completed.mean() - (
        (c.task_completed * c.w_att).sum() / c.w_att.sum()
    )
    nn_b = NearestNeighbors(n_neighbors=1).fit(c[["p"]].values)
    _, idx_b = nn_b.kneighbors(t[["p"]].values)
    match = (
        t.task_completed.values
        - c.task_completed.values[idx_b.flatten()]
    ).mean()
    return ate, att, match

rng = np.random.default_rng(7)
n_reps = 500
results = np.zeros((n_reps, 3))
for i in range(n_reps):
    boot = df.iloc[rng.integers(0, len(df), size=len(df))]
    results[i] = estimate_all(boot)

for name, col in zip(["IPW ATE", "IPW ATT", "1-NN ATT"], range(3)):
    lo, hi = np.percentile(results[:, col], [2.5, 97.5])
    print(f"{name:<10} 95% CI: [{lo:+.4f}, {hi:+.4f}]")

متوقع پیداوار:

IPW ATE    95% CI: [+0.0745, +0.0954]
IPW ATT    95% CI: [+0.0687, +0.0865]
1-NN ATT   95% CI: [+0.0659, +0.0940]

موجودہ صورتحال کچھ یوں ہے: ہم ڈیٹا سیٹ کو 500 بار تبدیل کرتے ہیں، پروپینسیٹی ماڈل کو ریفٹ کرتے ہیں، ہر تخمینہ لگانے والے کو ہر ایک نمونے کے لیے دوبارہ شمار کرتے ہیں، اور بوٹسٹریپ کی تقسیم کے 2.5ویں اور 97.5ویں پرسنٹائل کو 95% اعتماد کے وقفوں کے طور پر استعمال کرتے ہیں۔ تینوں وقفوں میں گراؤنڈ ٹروتھ +0.08 شامل ہیں اور بڑے مارجن سے Naive +0.21 کو خارج کرتے ہیں۔

IPW ATT وقفہ سب سے سخت ہے کیونکہ ATT صرف کنٹرول گروپ کو ری ویٹ کرتا ہے۔ سنگل پڑوسی مماثلت میں سب سے زیادہ 1-NN مماثلت کا وقفہ ہوتا ہے کیونکہ یہ مماثل سیٹ سے باہر کنٹرول صارفین کو ضائع کر دیتا ہے۔

اسے ایک بار چلانے میں میرے لیپ ٹاپ پر تقریباً 90 سیکنڈ لگتے ہیں۔ اسٹیک ہولڈر کی رپورٹس کے لیے، تخمینے اور اقتباس کے وقفوں کے لیے ہیڈ لائن کو اینکر کریں تاکہ ٹیم نمبروں کے ساتھ ساتھ غیر یقینی صورتحال دیکھ سکے۔

جب پروپینسٹی سکور کے طریقے ناکام ہو جاتے ہیں۔

جب مفروضے برقرار رہتے ہیں تو رجحان کے اسکور باخبر رضامندی کے موازنہ کو سخت بناتے ہیں۔ وہ متعصبانہ اندازے لگاتے ہیں جو صاف ظاہر ہوتے ہیں جب وہ مفروضے ناکام ہو جاتے ہیں۔

چار عام ناکامی کے طریقے تین پچھلے شناختی مفروضوں کا نقشہ بناتے ہیں۔

1. بے حساب کنفاؤنڈرز

اگر کوئی چیز آپٹ اِن اور نتیجہ دونوں کو چلاتی ہے لیکن پروپینسٹی ماڈل میں نہیں ہے، تو IPW اور مماثلت متعصب اندازے پیدا کرے گی۔ یہ دراصل سب سے عام ناکامی ہے۔

مثال: ایک صارف جو ایجنٹ موڈ کا انتخاب کرتا ہے وہ بھی ایک صارف ہے جو انجینئرنگ بلاگز کی پیروی کرتا ہے اور ریلیز نوٹس پڑھتا ہے۔ اگر بلاگ پڑھنے کا رویہ خصوصیات سے قطع نظر کام کی تکمیل کو بڑھاتا ہے، تو اس سگنل کی کمی ایجنٹ موڈ کو متاثر کرے گی، تخمینوں کو بڑھاتا ہے۔

صرف حقیقی دفاعوں میں آپٹ ان پروپینسیٹی ماڈلز، ڈومین کا علم ہے جو زیادہ فیچر انجینئرنگ کو آگے بڑھاتا ہے، اور باضابطہ حساسیت کے ٹولز (روزنبام باؤنڈز، ای ویلیوز) جو اس بات کا اندازہ لگاتے ہیں کہ نتائج کو الٹنے کے لیے کتنے طاقتور غیر پیمائشی کنفاؤنڈرز ہونے چاہئیں۔

2. تصدیق (نقل) ناکام ہو جاتی ہے (نقل کی خلاف ورزی)

اگر کچھ صارفین کے انتخاب کا امکان 0 (یا 1 کے قریب) کے قریب ہے، تو اس صارف کا کوئی موازنہ نہیں ہے۔ میں

PW انتہائی وزن (1 / 0.001 = 1,000) پیدا کرتا ہے جہاں ایک ہی آؤٹ لیئر تخمینہ پر غلبہ حاصل کر سکتا ہے۔ اس لیے ملاپ کو ناقص معیار کی جوڑی بنانے پر مجبور کیا جاتا ہے۔

رجحان ہسٹوگرام کو چیک کریں اور رجحان کو بیرونی طور پر بہتر کریں۔ [0.05, 0.95] وزن سے پہلے جب انتہائی قدریں موجود ہوں۔

3. غلط بیان کردہ رجحان کا ماڈل (ذلت آمیز، حقیقت میں الجھانے والا نہیں)

لکیری لاجسٹک ریگریشن نان لائنر تعلقات کو حاصل نہیں کر سکتی۔ اگر انتخاب شرکت کی پرت اور استفسار کے اعتماد کے درمیان تعامل پر منحصر ہے (پیچیدہ سوالات کے ساتھ طاقت استعمال کرنے والے منتخب کریں گے، ہلکے صارفین پاس ہوں گے)، اہم اثرات کا ماڈل اس سے محروم ہو جائے گا اور اس کا توازن خراب ہوگا۔

لچکدار ماڈلز کا استعمال کریں (مثلاً پروپینسٹی سکور پر گریڈینٹ بڑھانا یا وزن کی بنیاد پر ریگریشن اسکیلنگ) اور وزن دینے کے بعد ہمیشہ بیلنس چیک کریں۔ وزن کے بعد ناقص توازن تصریح کی غلطی کی ایک اہم علامت ہے۔

4. صارفین کے درمیان پھیلاؤ (SUTVA کی خلاف ورزی)

پروپینسٹی سکور کے طریقے یہ فرض کرتے ہیں کہ صارف خود مختار ہیں۔ اگر ایک صارف جو ایجنٹ موڈ کا انتخاب کرتا ہے کسی دوسرے صارف کے کام کی تکمیل پر اثر انداز ہوتا ہے (مثال کے طور پر، جب ٹیم کے اراکین مشترکہ ورک اسپیس میں ایک خصوصیت کو اپناتے ہیں)، تو متوقع اثر میں ایک لہر کا اثر شامل ہوتا ہے۔

یہ مستحکم یونٹ پروسیسنگ ویلیو کے مفروضے کی خلاف ورزی کرتا ہے، اور اسے صاف ستھرا طریقے سے سنبھالنے کے لیے دیگر ٹول کٹس کی ضرورت ہوتی ہے، جیسے کہ ورک اسپیس کی سطح پر اختیار کردہ خصوصیات کے لیے کلسٹر رینڈمائزیشن یا صارف کی سطح کے رساو کے لیے نیٹ ورک سے آگاہ تجرباتی ڈیزائن۔

یہ ناکامی کے طریقوں کو ریگریشن گتانک میں نہیں دکھایا گیا ہے۔ یہ وہ تخمینے ہیں جو کاغذ پر اچھے لگتے ہیں لیکن ایک بار جب فیچر کو مزید صارفین تک پہنچا دیا جاتا ہے تو وہ برقرار نہیں رہتے۔

بیلنس ڈائیگناسٹک چلائیں، ڈپلیکیٹ خاکوں کی جانچ کریں، اور جو کچھ بھی آپ سے چھوٹ گیا ہو اسے دستاویز کریں۔ یہ آپ کا واحد حقیقی دفاع ہے۔

آگے کیا کرنا ہے۔

جب آپٹ ان ٹوگل کے پیچھے خصوصیت فراہم کی جاتی ہے اور ماڈل کے انتخاب کے لیے کوویریٹس کی ایک دولت دستیاب ہوتی ہے تو پروپینسیٹی سکور کا طریقہ ایک موزوں ٹول ہے۔

اگر آپٹ ان واضح اصولوں کی پیروی کرتا ہے (استفسار کی پیچیدگی کی حد، ادائیگی والے درجے کے دروازے)، رجعت کا سلسلہ زیادہ مناسب ہے۔ اگر غیر مشاہدہ کنفاؤنڈرز کا شبہ ہے اور بیرونی بے ترتیب ذرائع (بے ترتیب رول آؤٹ شور، شرح کو محدود کرنے سے ٹرگرڈ روٹنگ) موجود ہیں، تو انسٹرومینٹل متغیرات بہتر کام کرتے ہیں۔

تخمینوں کو غلط رجحان کی تصریحات سے بچانے کے لیے، دوگنا مضبوط تخمینہ لگانے والا رجحان کے وزن اور رجعت کی ایڈجسٹمنٹ کو یکجا کرتا ہے اور جب دو جزو ماڈلز میں سے کم از کم ایک صحیح طریقے سے متعین کیا جاتا ہے تو مستقل رہتا ہے۔

اس ٹیوٹوریل کے لیے ساتھی نوٹ بک یہاں ہے۔ ریپوزٹری کو کلون کریں، ایک مصنوعی ڈیٹاسیٹ بنائیں، اور اسے چلائیں۔ psm_demo.ipynb (یا psm_demo.py) اس ٹیوٹوریل میں ہر کوڈ بلاک، ہر نمبر، اور ہر تصویر کو دوبارہ پیش کرتا ہے۔

جب ٹوگل کے بعد ایک AI فنکشن فراہم کیا جاتا ہے، تو سادہ انتخاب کا موازنہ عام طور پر ایک برا نمبر ہوتا ہے۔ پروپینسیٹی سکور کے طریقے "اس آئٹم پر کلک کرنے والے صارفین سے موازنہ کرنے والے صارفین" کا جوابی حقائق فراہم کرتے ہیں، جب کہ بوٹسٹریپنگ ایک قابل دفاع وقفہ فراہم کرتی ہے جب اسٹیک ہولڈرز سے پوچھا جاتا ہے کہ وہ کتنے پراعتماد ہیں۔

Scroll to Top