import%20marimo%0A%0A__generated_with%20%3D%20%220.20.4%22%0Aapp%20%3D%20marimo.App(width%3D%22full%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%20%20%F0%9F%8E%AF%20Ad%20Click%20Prediction%20Project%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%23%20Data%20Processing%20and%20Visualization%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20seaborn%20as%20sns%0A%0A%20%20%20%20%23%20Sklearn%3A%20Model%20Selection%20and%20Preprocessing%0A%20%20%20%20from%20sklearn.model_selection%20import%20train_test_split%0A%20%20%20%20from%20sklearn.preprocessing%20import%20StandardScaler%2C%20OneHotEncoder%0A%20%20%20%20from%20sklearn.compose%20import%20ColumnTransformer%0A%20%20%20%20from%20sklearn.pipeline%20import%20Pipeline%0A%0A%0A%0A%0A%20%20%20%20%23%20Sklearn%3A%20Machine%20Learning%20Models%0A%20%20%20%20from%20sklearn.linear_model%20import%20LogisticRegression%0A%20%20%20%20from%20sklearn.ensemble%20import%20RandomForestClassifier%2C%20GradientBoostingClassifier%0A%0A%0A%0A%0A%20%20%20%20%23%20Sklearn%3A%20Metrics%20and%20Evaluation%0A%20%20%20%20from%20sklearn.metrics%20import%20accuracy_score%2C%20roc_auc_score%2C%20classification_report%2C%20confusion_matrix%2C%20roc_curve%2C%20auc%0A%20%20%20%20from%20sklearn.model_selection%20import%20GridSearchCV%0A%20%20%20%20import%20shap%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20ColumnTransformer%2C%0A%20%20%20%20%20%20%20%20GradientBoostingClassifier%2C%0A%20%20%20%20%20%20%20%20GridSearchCV%2C%0A%20%20%20%20%20%20%20%20LogisticRegression%2C%0A%20%20%20%20%20%20%20%20RandomForestClassifier%2C%0A%20%20%20%20%20%20%20%20StandardScaler%2C%0A%20%20%20%20%20%20%20%20accuracy_score%2C%0A%20%20%20%20%20%20%20%20auc%2C%0A%20%20%20%20%20%20%20%20classification_report%2C%0A%20%20%20%20%20%20%20%20confusion_matrix%2C%0A%20%20%20%20%20%20%20%20mo%2C%0A%20%20%20%20%20%20%20%20pd%2C%0A%20%20%20%20%20%20%20%20plt%2C%0A%20%20%20%20%20%20%20%20roc_auc_score%2C%0A%20%20%20%20%20%20%20%20roc_curve%2C%0A%20%20%20%20%20%20%20%20sns%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_(pd%2C%20sns)%3A%0A%20%20%20%20sns.set_theme(style%3D%22whitegrid%22%2C%20palette%3D%22muted%22)%0A%20%20%20%20advertising_df%20%3D%20pd.read_csv(%22data%2Fraw%2Fadvertising.csv%22)%0A%20%20%20%20return%20(advertising_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20%23%20DATA%20DICTIONARY%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%7C%20Column%20%7C%20Description%20%7C%20Details%7C%0A%20%20%20%20%7C%20%3A---%20%7C%20%3A---%20%7C%20%3A---%20%7C%0A%20%20%20%20%7C%20**Daily%20Time%20Spent%20on%20Site**%20%7C%20consumer%20time%20on%20site%20in%20minutes%0A%20%20%20%20%7C%20**Age**%20%7C%20customer%20age%20in%20years%0A%20%20%20%20%7C%20**Area%20Income**%20%7C%20Avg.%20Income%20of%20geographical%20area%20of%20consumer%0A%20%20%20%20%7C%20**Daily%20Internet%20Usage**%20%7C%20Avg.%20minutes%20a%20day%20consumer%20is%20on%20the%20internet%0A%20%20%20%20%7C%20**Ad%20Topic%20Line**%20%7C%20Headline%20of%20the%20advertisement%0A%20%20%20%20%7C%20**City**%20%7C%20City%20of%20consumer%0A%20%20%20%20%7C%20**Male**%20%7C%20Whether%20or%20not%20consumer%20was%20male%0A%20%20%20%20%7C%20**Country**%20%7C%20Country%20of%20consumer%0A%20%20%20%20%7C%20**Timestamp**%20%7C%20Time%20at%20which%20consumer%20clicked%20on%20Ad%20or%20closed%20window%0A%20%20%20%20%7C%20**Clicked%20on%20Ad**%20%7C%200%20or%201%20indicated%20clicking%20on%20Ad%20%7C%20**(TARGET)**%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo)%3A%0A%20%20%20%20%23%20LOADING%20%26%20SHOWING%20DATA%0A%20%20%20%20rows%2C%20columns%20%3D%20advertising_df.shape%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%8E%AF%20Ad%20Click%20Prediction%20Project%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(f%22%23%23%23%23%20Total%20Records%3A%20**%7Brows%7D**%20%7C%20Total%20Columns%3A%20**%7Bcolumns%7D**%22)%2C%0A%20%20%20%20%20%20%20%20mo.ui.table(%0A%20%20%20%20%20%20%20%20%20%20%20%20advertising_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20label%3D%22Advertising%20Data%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20selection%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pagination%3DTrue%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20pd)%3A%0A%20%20%20%20%23%20DATA%20QUALITY%20%26%20PROFILING%0A%20%20%20%20%23%20Check%20for%20missing%20values%20and%20duplicates%2C%20unique%20values%0A%20%20%20%20missing_values%20%3D%20advertising_df.isna().sum()%0A%20%20%20%20duplicate_count%20%3D%20advertising_df.duplicated().sum()%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%94%8D%20Data%20Quality%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(f%22%23%23%23%23%20Duplicates%3A%20**%7Bduplicate_count%7D**%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(f%22%23%23%23%23%20Missing%20Values%3A%20**%7Bmissing_values.sum()%7D**%22)%2C%0A%20%20%20%20%20%20%20%20mo.ui.table(%0A%20%20%20%20%20%20%20%20%20%20%20%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Data%20Type%22%3A%20advertising_df.dtypes.astype(str)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Unique%20Values%22%3A%20advertising_df.nunique()%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20selection%3DNone%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20pd%2C%20plt%2C%20sns)%3A%0A%20%20%20%20%23%20TARGET%20DISTRIBUTION%0A%20%20%20%20target_counts%20%3D%20advertising_df%5B'Clicked%20on%20Ad'%5D.value_counts()%0A%20%20%20%20target_percent%20%3D%20(advertising_df%5B'Clicked%20on%20Ad'%5D.value_counts(normalize%3DTrue)%20*%20100).round(2).astype(str)%20%2B%20'%25'%0A%0A%20%20%20%20target_summary%20%3D%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22Count%22%3A%20target_counts%2C%0A%20%20%20%20%20%20%20%20%22Percentage%20(%25)%22%3A%20target_percent%0A%20%20%20%20%7D)%0A%0A%20%20%20%20fig%2C%20ax%20%3D%20plt.subplots(figsize%3D(5%2C%204))%0A%20%20%20%20sns.countplot(%0A%20%20%20%20%20%20%20%20data%3Dadvertising_df%2C%20%0A%20%20%20%20%20%20%20%20x%3D'Clicked%20on%20Ad'%2C%20%0A%20%20%20%20%20%20%20%20palette%3D%5B'%233498db'%2C%20'%23e74c3c'%5D%2C%20%0A%20%20%20%20%20%20%20%20hue%3D'Clicked%20on%20Ad'%2C%20%0A%20%20%20%20%20%20%20%20legend%3DFalse%2C%20%0A%20%20%20%20%20%20%20%20ax%3Dax%0A%20%20%20%20)%0A%0A%20%20%20%20ax.set_title(%22Visual%20Balance%20(0%20vs%201)%22)%0A%20%20%20%20ax.set_xlabel(%22Clicked%20on%20Ad%20(0%20%3D%20No%2C%201%20%3D%20Yes)%22)%0A%20%20%20%20ax.set_ylabel(%22Count%22)%0A%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%8E%AF%20Target%20Variable%20Distribution%22)%2C%0A%20%20%20%20%20%20%20%20mo.hstack(%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.ui.table(target_summary%2C%20selection%3DNone)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fig%0A%20%20%20%20%20%20%20%20%5D%2C%20justify%3D%22start%22%2C%20gap%3D4)%0A%20%20%20%20%5D)%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%23%23%23%20%F0%9F%8E%AF%20Target%20Variable%20Conclusion%20%26%20Strategy%0A%0A%20%20%20%20*%20**Perfectly%20Balanced%20Dataset%3A**%20The%20target%20variable%20(%22Clicked%20on%20Ad%22)%20is%20perfectly%20balanced%20(50%25%20vs%2050%25%2C%20with%20exactly%20500%20instances%20per%20class).%20This%20is%20the%20ideal%20scenario%20for%20model%20training.%0A%20%20%20%20*%20**Evaluation%20Metrics%3A**%20Because%20the%20classes%20are%20equal%2C%20**Accuracy**%20will%20be%20a%20reliable%20primary%20metric%20for%20evaluating%20overall%20performance.%20However%2C%20to%20align%20with%20business%20objectives%20(e.g.%2C%20optimizing%20ad%20spend)%2C%20we%20will%20also%20analyze%20**Precision**%20and%20**Recall**%20to%20understand%20the%20specific%20types%20of%20prediction%20errors.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo)%3A%0A%20%20%20%20%23%20STATISTICAL%20SUMMARY%0A%20%20%20%20stats%20%3D%20advertising_df.describe().T.round(2)%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%93%8A%20Statistical%20Overview%22)%2C%0A%20%20%20%20%20%20%20%20mo.ui.table(stats%2C%20selection%3DNone)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20plt%2C%20sns)%3A%0A%20%20%20%20%23%20Correlation%20Matrix%0A%20%20%20%20corr_matrix%20%3D%20advertising_df.corr(numeric_only%3DTrue)%0A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(10%2C%207))%0A%0A%20%20%20%20sns.heatmap(%0A%20%20%20%20%20%20%20%20corr_matrix%2C%0A%20%20%20%20%20%20%20%20annot%3DTrue%2C%0A%20%20%20%20%20%20%20%20fmt%3D%22.2f%22%2C%0A%20%20%20%20%20%20%20%20cmap%3D%22coolwarm%22%2C%0A%20%20%20%20%20%20%20%20linewidths%3D0.5%2C%0A%20%20%20%20%20%20%20%20ax%3D_ax%0A%20%20%20%20)%0A%0A%20%20%20%20_ax.set_title(%22Correlation%20Matrix%20of%20Ad%20Clicks%20Features%22%2C%20pad%3D20%2C%20fontsize%3D14%2C%20weight%3D'bold')%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%8C%A1%EF%B8%8F%20Feature%20Correlation%20Analysis%22)%2C%0A%20%20%20%20%20%20%20%20_fig%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%8C%A1%EF%B8%8F%20Feature%20Correlation%20Analysis%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20*%20**Primary%20Drivers%3A**%20%60Daily%20Internet%20Usage%60%20(-0.79)%20and%20%60Daily%20Time%20Spent%20on%20Site%60%20(-0.75)%20show%20the%20strongest%20negative%20correlation%20with%20ad%20clicks.%20This%20suggests%20that%20users%20who%20spend%20less%20time%20online%20are%20more%20likely%20to%20interact%20with%20these%20ads.%0A%20%20%20%20%20%20%20%20*%20**Demographic%20Impact%3A**%20%60Age%60%20(0.49)%20has%20a%20notable%20positive%20correlation%2C%20meaning%20older%20users%20in%20this%20dataset%20tend%20to%20click%20on%20ads%20more%20frequently.%0A%20%20%20%20%20%20%20%20*%20**Irrelevant%20Features%3A**%20The%20%60Male%60%20feature%20(-0.04)%20shows%20almost%20zero%20correlation%2C%20indicating%20that%20gender%20does%20not%20play%20a%20significant%20role%20in%20predicting%20clicks.%0A%20%20%20%20%20%20%20%20%22%22%22)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20sns)%3A%0A%20%20%20%20%23%20Daily%20Internet%20Usage%20vs%20Daily%20Time%20Spent%20on%20Site%20vs%20Target%0A%20%20%20%20joint_plot%20%3D%20sns.jointplot(%0A%20%20%20%20%20%20%20%20data%3Dadvertising_df%2C%20%0A%20%20%20%20%20%20%20%20x%3D'Daily%20Time%20Spent%20on%20Site'%2C%20%0A%20%20%20%20%20%20%20%20y%3D'Daily%20Internet%20Usage'%2C%20%0A%20%20%20%20%20%20%20%20hue%3D'Clicked%20on%20Ad'%2C%20%0A%20%20%20%20%20%20%20%20palette%3D'coolwarm'%2C%20%0A%20%20%20%20%20%20%20%20alpha%3D0.7%0A%20%20%20%20)%0A%20%20%20%20joint_fig%20%3D%20joint_plot.fig%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%93%88%20Daily%20Internet%20Usage%20vs%20Daily%20Time%20Spent%20on%20Site%22)%2C%0A%20%20%20%20%20%20%20%20joint_fig%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20*%20**Cluster%20Separation%3A**%20The%20Jointplot%20reveals%20two%20distinct%20groups.%20The%20%22High%20Usage%22%20group%20(blue)%2C%20who%20spend%20significant%20time%20on%20both%20the%20site%20and%20the%20internet%2C%20almost%20never%20click%20on%20the%20ad.%0A%20%20%20%20%20%20%20%20*%20**Target%20Audience%3A**%20The%20%22Low%20Usage%22%20group%20(red)%20is%20our%20primary%20target.%20They%20spend%20less%20time%20online%2C%20and%20they%20are%20the%20ones%20consistently%20interacting%20with%20the%20advertisement.%0A%20%20%20%20%20%20%20%20*%20**Model%20Predictability%3A**%20The%20classes%20are%20nearly%20perfectly%20separable.%20This%20is%20a%20strong%20indicator%20that%20our%20classification%20model%20will%20likely%20achieve%20very%20high%20accuracy.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20sns)%3A%0A%20%20%20%20%23%20Age%20vs%20Time%20on%20Site%20Analysis%20vs%20Target%0A%0A%20%20%20%20joint_plot_age_time%20%3D%20sns.jointplot(%0A%20%20%20%20%20%20%20%20data%3Dadvertising_df%2C%20%0A%20%20%20%20%20%20%20%20x%3D'Age'%2C%20%0A%20%20%20%20%20%20%20%20y%3D'Daily%20Time%20Spent%20on%20Site'%2C%20%0A%20%20%20%20%20%20%20%20hue%3D'Clicked%20on%20Ad'%2C%20%0A%20%20%20%20%20%20%20%20palette%3D'coolwarm'%2C%20%0A%20%20%20%20%20%20%20%20alpha%3D0.7%2C%0A%20%20%20%20%20%20%20%20kind%3D'scatter'%0A%20%20%20%20)%0A%20%20%20%20joint_fig_age_time%20%3D%20joint_plot_age_time.fig%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%93%88%20Age%20vs.%20Time%20on%20Site%20Analysis%22)%2C%0A%20%20%20%20%20%20%20%20joint_fig_age_time%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20*%20**Demographic%20Patterns%3A**%20There%20is%20a%20distinct%20split%20in%20behavior.%20Younger%20users%20with%20high%20site%20engagement%20(top-left)%20rarely%20click%20on%20ads%2C%20while%20older%20users%20with%20lower%20site%20engagement%20(bottom-right)%20are%20the%20primary%20clickers.%0A%20%20%20%20%20%20%20%20*%20**Negative%20Correlation%3A**%20The%20visual%20confirms%20the%20negative%20correlation%20between%20age%20and%20time%20spent%20on%20site.%0A%20%20%20%20%20%20%20%20*%20**High%20Separability%3A**%20The%20minimal%20overlap%20between%20classes%20suggests%20that%20our%20classification%20model%20will%20perform%20exceptionally%20well%20using%20these%20two%20features.%0A%20%20%20%20%20%20%20%20%22%22%22)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20mo%2C%20sns)%3A%0A%20%20%20%20%23%20Age%20vs%20Area%20incole%20vs%20Target%0A%20%20%20%20joint_plot_age_income%20%3D%20sns.jointplot(%0A%20%20%20%20%20%20%20%20data%3Dadvertising_df%2C%20%0A%20%20%20%20%20%20%20%20x%3D'Age'%2C%20%0A%20%20%20%20%20%20%20%20y%3D'Area%20Income'%2C%20%0A%20%20%20%20%20%20%20%20hue%3D'Clicked%20on%20Ad'%2C%20%0A%20%20%20%20%20%20%20%20palette%3D'coolwarm'%2C%20%0A%20%20%20%20%20%20%20%20alpha%3D0.7%0A%20%20%20%20)%0A%20%20%20%20joint_fig_age_income%20%3D%20joint_plot_age_income.fig%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%20%F0%9F%92%B0%20Age%20vs.%20Area%20Income%22)%2C%0A%20%20%20%20%20%20%20%20joint_fig_age_income%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20*%20**Noticeable%20Overlap%3A**%20Unlike%20previous%20plots%2C%20there's%20much%20more%20mixing%20here.%20Age%20and%20Income%20alone%20don't%20separate%20the%20groups%20perfectly.%0A%20%20%20%20%20%20%20%20*%20**General%20Trend%3A**%20We%20still%20see%20that%20older%20users%20with%20lower%20area%20income%20(bottom-right)%20are%20more%20likely%20to%20click%2C%20but%20it's%20less%20obvious.%0A%20%20%20%20%20%20%20%20*%20**Key%20Point%3A**%20These%20features%20are%20useful%2C%20but%20the%20model%20will%20definitely%20need%20the%20%22Time%20Spent%22%20metrics%20to%20reach%20high%20accuracy.%0A%20%20%20%20%20%20%20%20%22%22%22)%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df)%3A%0A%20%20%20%20advertising_df%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(advertising_df%2C%20pd)%3A%0A%20%20%20%20%23%20feature%20Engineering%0A%0A%20%20%20%20%23%20Copy%20the%20original%20dataset%0A%20%20%20%20processed_advertising%20%3D%20advertising_df.copy()%0A%0A%20%20%20%20%23%20Time%20Processing%20(Binning)%0A%20%20%20%20processed_advertising%5B'Timestamp'%5D%20%3D%20pd.to_datetime(processed_advertising%5B'Timestamp'%5D)%0A%0A%20%20%20%20%23%20Create%20is_weekend%3A%201%20if%20it's%20the%20weekend%20(index%205%20and%206)%2C%200%20otherwise%0A%20%20%20%20processed_advertising%5B'is_weekend'%5D%20%3D%20(processed_advertising%5B'Timestamp'%5D.dt.dayofweek%20%3E%3D%205).astype(int)%0A%0A%20%20%20%20%23%20Create%20is_evening%3A%201%20if%20it's%20evening%2Fnight%20(e.g.%2C%2018%3A00%20to%2023%3A59)%2C%200%20otherwise%0A%20%20%20%20processed_advertising%5B'is_evening'%5D%20%3D%20(processed_advertising%5B'Timestamp'%5D.dt.hour%20%3E%3D%2018).astype(int)%0A%0A%20%20%20%20columns_to_drop%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'City'%2C%20%0A%20%20%20%20%20%20%20%20'Country'%2C%20%0A%20%20%20%20%20%20%20%20'Timestamp'%2C%20%0A%20%20%20%20%20%20%20%20'Ad%20Topic%20Line'%0A%20%20%20%20%5D%0A%0A%20%20%20%20processed_advertising%20%3D%20processed_advertising.drop(columns%3Dcolumns_to_drop%2C%20errors%3D'ignore')%0A%0A%20%20%20%20processed_advertising%0A%20%20%20%20return%20(processed_advertising%2C)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ColumnTransformer%2C%0A%20%20%20%20StandardScaler%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20processed_advertising%2C%0A%20%20%20%20train_test_split%2C%0A)%3A%0A%20%20%20%20%23%20Data%20Preprocessing%20Pipeline%3A%20Train%2FTest%20Split%2C%20Scaling%0A%0A%20%20%20%20%23%20Separating%20features%20and%20target%0A%20%20%20%20X%20%3D%20processed_advertising.drop('Clicked%20on%20Ad'%2C%20axis%3D1)%0A%20%20%20%20y%20%3D%20processed_advertising%5B'Clicked%20on%20Ad'%5D%0A%0A%20%20%20%20%23%20Train%2FTest%20Split%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%2C%20y%2C%20%0A%20%20%20%20%20%20%20%20test_size%3D0.2%2C%20%0A%20%20%20%20%20%20%20%20random_state%3D42%2C%20%0A%20%20%20%20%20%20%20%20stratify%3Dy%0A%20%20%20%20)%0A%0A%20%20%20%20numeric_features%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'Daily%20Time%20Spent%20on%20Site'%2C%20%0A%20%20%20%20%20%20%20%20'Age'%2C%20%0A%20%20%20%20%20%20%20%20'Area%20Income'%2C%20%0A%20%20%20%20%20%20%20%20'Daily%20Internet%20Usage'%0A%20%20%20%20%5D%0A%0A%20%20%20%20binary_features%20%3D%20%5B'Male'%2C%20'is_weekend'%2C%20'is_evening'%5D%0A%0A%20%20%20%20%23%20ColumnTransformer%0A%20%20%20%20preprocessor%20%3D%20ColumnTransformer(%0A%20%20%20%20%20%20%20%20transformers%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20('num'%2C%20StandardScaler()%2C%20numeric_features)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20('bin'%2C%20'passthrough'%2C%20binary_features)%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20verbose_feature_names_out%3DFalse%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Output%20as%20Pandas%20DataFrame%0A%20%20%20%20preprocessor.set_output(transform%3D%22pandas%22)%0A%0A%20%20%20%20%23%20Fit%20%26%20Transform%0A%20%20%20%20X_train_processed%20%3D%20preprocessor.fit_transform(X_train)%0A%20%20%20%20X_test_processed%20%3D%20preprocessor.transform(X_test)%0A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20*%20**Training%20Data%3A**%20%7BX_train_processed.shape%7D%0A%20%20%20%20*%20**Testing%20Data%3A**%20%7BX_test_processed.shape%7D%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%20X_test_processed%2C%20X_train_processed%2C%20y_test%2C%20y_train%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20LogisticRegression%2C%0A%20%20%20%20X_test_processed%2C%0A%20%20%20%20X_train_processed%2C%0A%20%20%20%20accuracy_score%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20roc_auc_score%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20%23%20baseline%20Model%20(log%20regression)%0A%20%20%20%20%23%20initialize%20and%20train%20our%20simplest%2C%20baseline%20model%0A%20%20%20%20log_reg%20%3D%20LogisticRegression(random_state%3D42)%0A%20%20%20%20log_reg.fit(X_train_processed%2C%20y_train)%0A%0A%20%20%20%20%23%20predict%0A%20%20%20%20y_pred%20%3D%20log_reg.predict(X_test_processed)%0A%0A%20%20%20%20%23%20probabilities%20for%20the%20ROC-AUC%20metric%0A%20%20%20%20y_prob%20%3D%20log_reg.predict_proba(X_test_processed)%5B%3A%2C%201%5D%20%0A%0A%20%20%20%20%23%20calc%20ROC-AUC%0A%20%20%20%20acc%20%3D%20accuracy_score(y_test%2C%20y_pred)%0A%20%20%20%20roc_auc%20%3D%20roc_auc_score(y_test%2C%20y_prob)%0A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20%23%23%23%20%F0%9F%9A%80%20First%20Test%20Result%3A%20Logistic%20Regression%0A%0A%20%20%20%20*%20**Accuracy%3A**%20%60%7Bacc%3A.4f%7D%60%0A%20%20%20%20*%20**ROC-AUC%20Score%3A**%20%60%7Broc_auc%3A.4f%7D%60%20The%20closer%20to%201.0%2C%20the%20better%0A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(classification_report%2C%20confusion_matrix%2C%20mo%2C%20plt%2C%20roc_auc_score%2C%20sns)%3A%0A%20%20%20%20%23%20Create%20a%20universal%20function%20to%20evaluate%20all%20our%20models!%0A%20%20%20%20def%20evaluate_model(model%2C%20name%2C%20X_test%2C%20y_test)%3A%0A%0A%20%20%20%20%20%20%20%20y_pred%20%3D%20model.predict(X_test)%0A%20%20%20%20%20%20%20%20y_prob%20%3D%20model.predict_proba(X_test)%5B%3A%2C%201%5D%20%0A%0A%20%20%20%20%20%20%20%20%23%20Calculate%20metrics%0A%20%20%20%20%20%20%20%20roc_auc%20%3D%20roc_auc_score(y_test%2C%20y_prob)%0A%20%20%20%20%20%20%20%20report%20%3D%20classification_report(y_test%2C%20y_pred)%0A%0A%20%20%20%20%20%20%20%20%23%20Confusion%20Matrix%0A%20%20%20%20%20%20%20%20cm%20%3D%20confusion_matrix(y_test%2C%20y_pred%2C%20labels%3D%5B1%2C%200%5D)%0A%20%20%20%20%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%206))%0A%20%20%20%20%20%20%20%20sns.heatmap(cm%2C%20annot%3DTrue%2C%20fmt%3D'd'%2C%20cmap%3D'Blues'%2C%20cbar%3DFalse%2C%20ax%3D_ax%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20xticklabels%3D%5B'Clicked%20(1)'%2C%20'Not%20Clicked%20(0)'%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20yticklabels%3D%5B'Clicked%20(1)'%2C%20'Not%20Clicked%20(0)'%5D)%0A%20%20%20%20%20%20%20%20_ax.set_title(f'Confusion%20Matrix%3A%20%7Bname%7D'%2C%20weight%3D'bold')%0A%20%20%20%20%20%20%20%20plt.tight_layout()%0A%0A%20%20%20%20%20%20%20%20return%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22%23%23%23%20%F0%9F%A4%96%20Model%3A%20%7Bname%7D%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**ROC-AUC%20Score%3A**%20%60%7Broc_auc%3A.4f%7D%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(f%22**Classification%20Report%3A**%5Cn%60%60%60text%5Cn%7Breport%7D%5Cn%60%60%60%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_fig%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22---%22)%0A%20%20%20%20%20%20%20%20%5D)%0A%0A%0A%20%20%20%20return%20(evaluate_model%2C)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20GradientBoostingClassifier%2C%0A%20%20%20%20LogisticRegression%2C%0A%20%20%20%20RandomForestClassifier%2C%0A%20%20%20%20X_test_processed%2C%0A%20%20%20%20X_train_processed%2C%0A%20%20%20%20evaluate_model%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20%23%20Initialization%20Models%0A%20%20%20%20models%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22Logistic%20Regression%22%3A%20LogisticRegression(random_state%3D42)%2C%0A%20%20%20%20%20%20%20%20%22Random%20Forest%22%3A%20RandomForestClassifier(random_state%3D42%2C%20n_estimators%3D100)%2C%0A%20%20%20%20%20%20%20%20%22Gradient%20Boosting%22%3A%20GradientBoostingClassifier(random_state%3D42)%0A%20%20%20%20%7D%0A%0A%20%20%20%20results_ui%20%3D%20%5B%5D%0A%20%20%20%20for%20name%2C%20model%20in%20models.items()%3A%0A%20%20%20%20%20%20%20%20model.fit(X_train_processed%2C%20y_train)%0A%20%20%20%20%20%20%20%20ui_element%20%3D%20evaluate_model(model%2C%20name%2C%20X_test_processed%2C%20y_test)%0A%20%20%20%20%20%20%20%20results_ui.append(ui_element)%0A%0A%20%20%20%20%23%20display%20all%20reports%20together%0A%20%20%20%20mo.vstack(results_ui)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20*%20**Observation%3A**%20The%20simplest%20model%20(Logistic%20Regression)%20easily%20beat%20the%20complex%20ones%2C%20hitting%2097.5%25%20accuracy.%20It%20caught%20almost%20all%20real%20clicks%20flawlessly%20and%20saved%20our%20ad%20budget.%0A%20%20%20%20*%20**The%20%22Why%22%3A**%20Our%20dataset%20is%20small%20and%20highly%20logical.%20In%20these%20cases%2C%20complex%20models%20overcomplicate%20things%20and%20get%20confused%20by%20noise%20(overfitting).%20A%20simple%20model%20just%20draws%20a%20straight%20line%20and%20hits%20the%20target.%0A%20%20%20%20*%20**Next%20Step%3A**%20Try%20tuning%20the%20hyperparameters.%20Since%20this%20model%20is%20completely%20transparent%2C%20we%20can%20look%20inside%20its%20%22brain%22.%20Next%2C%20we%E2%80%99ll%20find%20out%20the%20most%20important%20thing%3A%20what%20exactly%20makes%20a%20user%20click%20the%20ad%20%E2%80%94%20age%2C%20income%2C%20or%20time%20spent%20on%20the%20site%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(GridSearchCV%2C%20LogisticRegression%2C%20X_train_processed%2C%20mo%2C%20y_train)%3A%0A%20%20%20%20%23%20Hyperparameter%20Tuning%20via%20GridSearchCV%20%0A%20%20%20%20param_grid%20%3D%20%7B%0A%20%20%20%20%20%20%20%20'C'%3A%20%5B0.01%2C%200.1%2C%201%2C%2010%2C%20100%5D%2C%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20'l1_ratio'%3A%20%5B0%2C%201%5D%2C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20'solver'%3A%20%5B'liblinear'%5D%2C%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20'max_iter'%3A%20%5B1000%5D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%7D%0A%0A%20%20%20%20%23%20grid_search%0A%20%20%20%20grid_search%20%3D%20GridSearchCV(%0A%20%20%20%20%20%20%20%20estimator%3DLogisticRegression(random_state%3D42)%2C%0A%20%20%20%20%20%20%20%20param_grid%3Dparam_grid%2C%0A%20%20%20%20%20%20%20%20cv%3D5%2C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20scoring%3D'accuracy'%2C%0A%20%20%20%20%20%20%20%20n_jobs%3D-1%2C%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20verbose%3D1%20%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20training%0A%20%20%20%20grid_search.fit(X_train_processed%2C%20y_train)%0A%0A%20%20%20%20best_log_reg%20%3D%20grid_search.best_estimator_%0A%20%20%20%20best_params%20%3D%20grid_search.best_params_%0A%20%20%20%20best_score%20%3D%20grid_search.best_score_%0A%0A%20%20%20%20%23%20display%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20*%20**Best%20Parameters%3A**%20%60%7Bbest_params%7D%60%0A%20%20%20%20*%20**Cross-Validation%20Accuracy%3A**%20%60%7Bbest_score%3A.4f%7D%60%0A%0A%20%20%20%20Now%20we%20can%20use%20this%20optimized%20model%20**%7Bbest_log_reg%7D**%20for%20the%20final%20evaluation%20and%20to%20extract%20the%20weights!!%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%20(best_log_reg%2C)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20X_test_processed%2C%0A%20%20%20%20X_train_processed%2C%0A%20%20%20%20best_log_reg%2C%0A%20%20%20%20evaluate_model%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20pd%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20sns%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20%23%20final%20evaluation%20on%20the%20test%20set%0A%20%20%20%20evaluation_ui%20%3D%20evaluate_model(best_log_reg%2C%20%22Optimized%20Logistic%20Regression%20(C%3D0.1)%22%2C%20X_test_processed%2C%20y_test)%0A%0A%20%20%20%20%23%20Extracting%20model%20weights%20and%20feature%20names%0A%20%20%20%20feature_names%20%3D%20X_train_processed.columns%0A%20%20%20%20coefficients%20%3D%20best_log_reg.coef_%5B0%5D%0A%0A%20%20%20%20%23%20Sorting%20weights%20in%20a%20DataFrame%20for%20visualization%0A%20%20%20%20coef_df%20%3D%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20'Feature'%3A%20feature_names%2C%0A%20%20%20%20%20%20%20%20'Weight'%3A%20coefficients%0A%20%20%20%20%7D).sort_values(by%3D'Weight'%2C%20ascending%3DFalse)%0A%0A%20%20%20%20%23%20Feature%20Importances%0A%20%20%20%20fig_weights%2C%20ax_weights%20%3D%20plt.subplots(figsize%3D(8%2C%206))%0A%0A%20%20%20%20%23%20Blue%20for%20positive%20impact%2C%20Red%20for%20negative%0A%20%20%20%20colors%20%3D%20%5B'%231f77b4'%20if%20w%20%3E%200%20else%20'%23d62728'%20for%20w%20in%20coef_df%5B'Weight'%5D%5D%0A%20%20%20%20sns.barplot(x%3D'Weight'%2C%20y%3D'Feature'%2C%20hue%3D'Feature'%2C%20data%3Dcoef_df%2C%20palette%3Dcolors%2C%20ax%3Dax_weights%2C%20legend%3DFalse)%0A%0A%20%20%20%20ax_weights.set_title('What%20drives%20the%20click%3F'%2C%20weight%3D'bold'%2C%20fontsize%3D14%2C%20pad%3D15)%0A%20%20%20%20ax_weights.set_xlabel('Feature%20Weight')%0A%20%20%20%20ax_weights.set_ylabel('')%0A%0A%20%20%20%20ax_weights.axvline(0%2C%20color%3D'black'%2C%20linewidth%3D1)%0A%20%20%20%20plt.tight_layout()%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20evaluation_ui%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%20%E2%9A%96%EF%B8%8F%20What%20Drives%20the%20Decision%3F%0A%20%20%20%20%20%20%20%20*%20**Right%20side%20(Blue)%3A**%20Factors%20that%20increase%20the%20likelihood%20of%20clicking.%0A%20%20%20%20%20%20%20%20*%20**Left%20side%20(Red)%3A**%20Factors%20that%20decrease%20the%20likelihood%20of%20clicking.%0A%20%20%20%20%20%20%20%20%22%22%22)%2C%0A%20%20%20%20%20%20%20%20fig_weights%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X_test_processed%2C%20auc%2C%20best_log_reg%2C%20mo%2C%20plt%2C%20roc_curve%2C%20y_test)%3A%0A%20%20%20%20%23%20Roc-Auc%20curve%0A%0A%20%20%20%20%23%20Getting%20probabilities%0A%20%20%20%20y_probs_final%20%3D%20best_log_reg.predict_proba(X_test_processed)%5B%3A%2C%201%5D%0A%0A%20%20%20%20%23%20Computing%20ROC%20%26%20AUC%0A%20%20%20%20fpr_final%2C%20tpr_final%2C%20_thresholds_final%20%3D%20roc_curve(y_test%2C%20y_probs_final)%0A%20%20%20%20roc_auc_value%20%3D%20auc(fpr_final%2C%20tpr_final)%0A%0A%20%20%20%20%23%20Visualization%0A%20%20%20%20fig_roc_final%2C%20ax_roc_final%20%3D%20plt.subplots(figsize%3D(8%2C%206))%0A%0A%20%20%20%20ax_roc_final.plot(fpr_final%2C%20tpr_final%2C%20color%3D'%231f77b4'%2C%20lw%3D3%2C%20label%3Df'ROC%20Curve%20(AUC%20%3D%20%7Broc_auc_value%3A.4f%7D)')%0A%20%20%20%20ax_roc_final.plot(%5B0%2C%201%5D%2C%20%5B0%2C%201%5D%2C%20color%3D'%237f7f7f'%2C%20lw%3D2%2C%20linestyle%3D'--')%0A%0A%20%20%20%20ax_roc_final.set_xlabel('False%20Positive%20Rate')%0A%20%20%20%20ax_roc_final.set_ylabel('True%20Positive%20Rate')%0A%20%20%20%20ax_roc_final.set_title('ROC%20Curve%20-%20Optimized%20Model'%2C%20weight%3D'bold')%0A%20%20%20%20ax_roc_final.legend(loc%3D%22lower%20right%22)%0A%20%20%20%20ax_roc_final.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20plt.tight_layout()%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%20%F0%9F%9B%A1%EF%B8%8F%20ROC-AUC%0A%20%20%20%20%20%20%20%20**Score%3A**%20%60%7Broc_auc_value%3A.4f%7D%60%0A%20%20%20%20%20%20%20%20%22%22%22)%2C%0A%20%20%20%20%20%20%20%20fig_roc_final%0A%20%20%20%20%5D)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20*%20**Core%20Drivers%3A**%20Who%20clicks%20the%20most%3F%20Older%20users%20(%60Age%60%20has%20the%20highest%20positive%20impact).%20Who%20ignores%20the%20ad%3F%20High-income%20(%60Area%20Income%60)%20and%20highly%20active%20digital%20users%20(those%20with%20high%20%60Daily%20Time%20on%20Site%60%20and%20%60Daily%20Internet%20Usage%60).%0A%20%20%20%20*%20**The%20Weekend%20Effect%3A**%20Our%20hypothesis%20was%20spot%20on!%20The%20%60is_weekend%60%20feature%20proves%20that%20ads%20get%20significantly%20more%20clicks%20on%20Saturdays%20and%20Sundays.%20A%20clear%20signal%20to%20reallocate%20the%20marketing%20budget.%0A%20%20%20%20*%20**Time%20%26%20Gender%20Impact%3A**%20Gender%20has%20a%20minor%20negative%20impact%2C%20while%20evening%20hours%20(%60is_evening%60)%20show%20almost%20zero%20effect.%0A%20%20%20%20*%20**A%20Cleaner%20Model%3A**%20Removing%20the%20geographical%20noise%20(countries)%20resulted%20in%20a%20much%20more%20stable%2C%20interpretable%2C%20and%20production-ready%20model.%0A%20%20%20%20%22%22%22)%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
56191afbd4a65fde1a9f4efb935f7c7b