<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: marcos-Nieves-24</title>
    <description>The latest articles on DEV Community by marcos-Nieves-24 (@marcosnieves24).</description>
    <link>https://dev.to/marcosnieves24</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4180464%2Fdc9c8081-acbd-4e99-9efc-da19f4da5792.png</url>
      <title>DEV Community: marcos-Nieves-24</title>
      <link>https://dev.to/marcosnieves24</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcosnieves24"/>
    <language>en</language>
    <item>
      <title>Accuracy Lied to Me: Precision, Recall, ROC AUC and Cross-Validation in ML Zoomcamp Module 4</title>
      <dc:creator>marcos-Nieves-24</dc:creator>
      <pubDate>Mon, 19 Oct 2026 21:48:59 +0000</pubDate>
      <link>https://dev.to/marcosnieves24/accuracy-lied-to-me-precision-recall-roc-auc-and-cross-validation-in-ml-zoomcamp-module-4-47n6</link>
      <guid>https://dev.to/marcosnieves24/accuracy-lied-to-me-precision-recall-roc-auc-and-cross-validation-in-ml-zoomcamp-module-4-47n6</guid>
      <description>&lt;p&gt;In Module 3 I trained a lead-scoring classifier and reported 0.645 accuracy. It sounded fine. Module 4 of ML Zoomcamp exists to&lt;br&gt;
destroy exactly that feeling — accuracy hides everything interesting when classes are imbalanced. Here is what I actually learned,&lt;br&gt;
with the numbers from my homework notebook. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;AUC as a feature-importance flashlight &lt;br&gt;
Before training anything, I scored every numerical column by using it raw as the prediction and computing ROC AUC against the&lt;br&gt;
target (negating it when AUC &amp;lt; 0.5, which just means negative correlation): &lt;br&gt;
annual_income: 0.608&lt;br&gt;
number_of_courses_viewed: 0.723&lt;br&gt;
interaction_count: 0.765&lt;br&gt;
lead_score: 0.788 ← winner &lt;br&gt;
Two lessons. First, lead_score alone already separates the classes decently — good to know before blaming the model. Second,&lt;br&gt;
the trap: if you loop over all numeric columns naively you also score converted against itself and get a perfect 1.000. I had that bug.&lt;br&gt;
Exclude the target. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The model: AUC 0.732, and why accuracy is not the story &lt;br&gt;
One-hot encoding with DictVectorizer (fit on train only), logistic regression with solver="liblinear", C=1.0, probabilities&lt;br&gt;
from predict_proba. Validation AUC: 0.732. &lt;br&gt;
AUC'sasts interpretation is my favourite thing in the module: it is the probability that a random positive outranks a random negative.&lt;br&gt;
My model ranks a random converter above a random non-converter 73% of the time. One number, no threshold chosen, immune to&lt;br&gt;
class balance. Accuracy can’t say any of that. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The threshold tradeoff is real (plot it!) &lt;br&gt;
Sweeping thresholds 0.00–1.00 in 0.01 steps: precision climbs, recall falls, they cross at 0.63 (P≈0.733, R≈0.725). F1 peaks earlier, at&lt;br&gt;
0.41 (F1≈0.758). The default 0.5 threshold is optimal for nothing — it is just the default. If missing a converter costs you more than a&lt;br&gt;
wasted email, you live left of 0.5; if spam costs more, right of it. The plot decides, not the default. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cross-validation: std is the point, and the solver is the trap &lt;br&gt;
5-fold CV (KFold(n_splits=5, shuffle=True, random_state=1)), fresh vectorizer per fold, AUC per fold: 0.731, 0.730,&lt;br&gt;
0.736, 0.741, 0.721. Mean ≈ 0.732, std 0.007. The std is the deliverable — it says how much I’d trust this number on new data. &lt;br&gt;
And here is the bug that would have failed the homework: the spec says solver="liblinear". Writing just&lt;br&gt;
LogisticRegression(max_iter=1000) silently uses lbfgs, which throws ConvergenceWarning on this data and lands on std&lt;br&gt;
0.013 — a different multiple-choice option. Same data, same seed, wrong solver, wrong answer. Read the spec, copy the constructor&lt;br&gt;
exactly. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tuning C: regularization you can see &lt;br&gt;
Same 5-fold loop over C in [1e-06, 0.001, 1]:C=1e-06 → 0.617 ± 0.019 (regularization crushes the weights: underfit)&lt;br&gt;
C=0.001 → 0.749 ± 0.010 ← best&lt;br&gt;
C=1 → 0.732 ± 0.007 &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tiny C is not “safer”, it is a model that barely learns. The sweep makes the bias-variance tradeoff visible instead of theoretical. &lt;br&gt;
Takeaway: 0.65 accuracy told me my Module 3 model “works”. Module 4 told me what it actually does: ranks decently (0.732), forces&lt;br&gt;
a precision/recall choice nobody made at 0.5, is stable across folds (±0.007), and tunes to C=0.001. I trust the second description.&lt;br&gt;
Don’t report accuracy alone again. &lt;br&gt;
Repo: &lt;a href="https://github.com/marcos-Nieves-24/machine-learning-zoomcamp/blob/main/homework-4/homework-4.ipynb" rel="noopener noreferrer"&gt;https://github.com/marcos-Nieves-24/machine-learning-zoomcamp/blob/main/homework-4/homework-4.ipynb&lt;/a&gt; &lt;/p&gt;

</description>
      <category>mlzoomcamp</category>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Module 3: Machine Learning for Classification from ML Zoomcamp 2026</title>
      <dc:creator>marcos-Nieves-24</dc:creator>
      <pubDate>Mon, 12 Oct 2026 21:58:45 +0000</pubDate>
      <link>https://dev.to/marcosnieves24/module-3-machine-learning-for-classification-from-ml-zoomcamp-2026-38kn</link>
      <guid>https://dev.to/marcosnieves24/module-3-machine-learning-for-classification-from-ml-zoomcamp-2026-38kn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp0h0dng21bblij2t36gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp0h0dng21bblij2t36gp.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just completed Module 3: Machine Learning for Classification from ML Zoomcamp 2026 🎉&lt;/p&gt;

&lt;p&gt;This module covered:&lt;br&gt;
🔹 Training and using logistic regression models&lt;br&gt;
🔹 Encoding categorical variables with one-hot encoding&lt;br&gt;
🔹 Measuring feature importance with the mutual information score&lt;br&gt;
🔹 Selecting useful features through feature elimination&lt;br&gt;
🔹 Interpreting what a classification model actually learned&lt;/p&gt;

&lt;p&gt;✨ My key takeaway: correlation and mutual information answer different questions. The biggest correlation in the dataset was interaction_count × lead_score, but the feature with the highest mutual information score with the target was lead_source, a categorical feature that a correlation matrix literally cannot see. If I had ranked features by correlation alone, I would have gotten it wrong.&lt;/p&gt;

&lt;p&gt;🤔 Something I found interesting: in the feature elimination exercise, removing number_of_courses_viewed cost 0.002 accuracy, while removing interaction_count cost (0.044). A gap that smalllooked like noise to me, so I re-ran the whole comparison with a second one-hot encoding approach to confirm it was deterministic and not an artifact of the library. It was. Small differences deserve verification before you dismiss them as noise.&lt;/p&gt;

&lt;p&gt;➡️ Next step → Module 4: Evaluation Metrics for Classification.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>machinelearning</category>
      <category>mlzoomcamp</category>
    </item>
  </channel>
</rss>
