<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Guides pratiques - Blog IA Engineering</title>
    <link>https://clement-reboul.fr/tags/guides-pratiques/</link>
    <description>Tutoriels de machine learning en Python, pas à pas : régression, classification, clustering, préparation des données.</description>
    <language>fr-FR</language>
    <lastBuildDate>Thu, 05 Nov 2026 14:34:27 GMT</lastBuildDate>
    <atom:link href="https://clement-reboul.fr/tags/guides-pratiques/feed.xml" rel="self" type="application/rss+xml" />
    <copyright>© 2025 Clément Reboul</copyright>
    <category>Technology</category>
    <category>Artificial Intelligence</category>
    <category>Machine Learning</category>
    <item>
      <title><![CDATA[Encodage de Variables Catégorielles : Du Texte aux Nombres pour le Machine Learning]]></title>
      <link>https://clement-reboul.fr/blog/encodage-de-variables-categorielles-du-texte-aux-nombres-pour-le-machine-learning/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/encodage-de-variables-categorielles-du-texte-aux-nombres-pour-le-machine-learning/</guid>
      <description><![CDATA[Les algorithmes de Machine Learning ne comprennent que les nombres. Comment transformer des catégories textuelles (« Jeune », « Adulte », « Mature ») en valeurs numériques exploitables ? Ce guide pratique détaille trois techniques d'encodage essentielles : le mapping binaire simple (OUI/NON → 0/1), l'encodage ordinal pour les progressions logiques, et l'encodage binaire pour les variables nominales à haute cardinalité. Basé sur un dataset réel de 42 588 arbres parisiens, ce tutoriel illustre les pièges à éviter (hiérarchies artificielles, double encodage) et fournit des analogies concrètes (interrupteurs, niveaux scolaires, codes-barres) pour comprendre le « pourquoi » derrière chaque méthode. Un incontournable pour maîtriser le preprocessing des données catégorielles avant l'entraînement de modèles ML.]]></description>
      <content:encoded><![CDATA[<p>Le preprocessing des données est une étape critique en Machine Learning, souvent sous-estimée mais déterminante pour la performance d&#39;un modèle. Une des transformations les plus fondamentales consiste à convertir les <strong>variables catégorielles</strong> (texte) en <strong>variables numériques</strong> (nombres). Pourquoi ? Parce que les algorithmes de Machine Learning — qu&#39;il s&#39;agisse de régression linéaire, de forêts aléatoires ou de réseaux de neurones — ne manipulent que des tenseurs numériques. Ils ne peuvent pas &quot;comprendre&quot; directement qu&#39;un arbre est &quot;Mature&quot; ou &quot;Jeune&quot;.</p>
<p>Dans ce guide, nous allons analyser en profondeur <strong>trois techniques d&#39;encodage</strong> appliquées à un dataset réel de 42 588 arbres parisiens (Platanes), en expliquant les fondements théoriques, les pièges à éviter, et les bonnes pratiques industrielles.</p>
<hr>
<h2>Le Dataset : Arbres Remarquables de Paris</h2>
<p>Nous travaillons sur un sous-ensemble du <strong>patrimoine arboré parisien</strong>, filtré sur les Platanes uniquement. Ce dataset contient plusieurs variables catégorielles représentatives des défis courants en Data Science :</p>
<ul>
<li><strong><code>remarquable</code></strong> : Variable binaire (OUI/NON) indiquant si l&#39;arbre a un intérêt historique ou esthétique exceptionnel</li>
<li><strong><code>stade_de_developpement</code></strong> : Variable ordinale (Jeune → Adulte → Mature) avec une progression logique</li>
<li><strong><code>espece</code></strong> : Variable nominale (Platane, Chêne, Érable, etc.) sans hiérarchie naturelle</li>
</ul>
<p>Ce cas d&#39;usage est idéal pour illustrer les trois familles d&#39;encodage : <strong>binaire</strong>, <strong>ordinal</strong> et <strong>nominal</strong>.</p>
<hr>
<h2>Problématique Technique : Pourquoi les Catégories Doivent Devenir des Nombres</h2>
<h3>L&#39;Incompatibilité Fondamentale</h3>
<p>Les algorithmes ML reposent sur des opérations mathématiques : multiplication matricielle, calcul de distances euclidiennes, gradients de fonctions de coût. Ces opérations nécessitent des <strong>valeurs numériques</strong>.</p>
<p><strong>Exemple concret</strong> : Si on entraîne un modèle de régression pour prédire la hauteur d&#39;un arbre à partir de son stade de développement, l&#39;algorithme a besoin de calculer :</p>
<pre><code>Hauteur prédite = w₁ × stade + w₂ × circonférence + b
</code></pre>
<p>Si <code>stade = &quot;Adulte&quot;</code> (chaîne de caractères), cette équation n&#39;a aucun sens mathématique. Il faut transformer &quot;Adulte&quot; en un nombre (par exemple, 3).</p>
<h3>Le Piège de l&#39;Encodage Naïf</h3>
<p>La solution la plus simple serait d&#39;assigner arbitrairement :</p>
<ul>
<li>Jeune → 1</li>
<li>Adulte → 2</li>
<li>Mature → 3</li>
</ul>
<p>Mais cette approche fonctionne <strong>uniquement si l&#39;ordre a du sens</strong> (variables ordinales). Pour des catégories nominales comme les espèces d&#39;arbres, cela créerait une hiérarchie artificielle que le modèle pourrait mal interpréter. Par exemple, si Chêne=1, Érable=2, Platane=3, le modèle pourrait &quot;apprendre&quot; que Platane = Chêne + Érable, ce qui est absurde.</p>
<hr>
<h2>Technique 1 : Encodage Binaire Manuel (0/1) — La Variable <code>remarquable</code></h2>
<h3>Contexte et Distribution</h3>
<p>La variable <code>remarquable</code> est une <strong>variable binaire</strong> : un arbre est soit remarquable (OUI), soit ordinaire (NON). C&#39;est le cas le plus simple d&#39;encodage catégoriel.</p>
<p><strong>Distribution observée</strong> :</p>
<ul>
<li>NON : 42 493 arbres (99.8%)</li>
<li>OUI : 95 arbres (0.2%)</li>
</ul>
<p>Cette distribution <strong>déséquilibrée</strong> (class imbalance) est typique des problèmes de classification d&#39;événements rares (fraude bancaire, pannes industrielles, etc.).</p>
<h3>Méthode d&#39;Encodage</h3>
<p>L&#39;encodage manuel est direct et explicite :</p>
<pre><code class="language-python">df.loc[df.remarquable == &quot;NON&quot;, &quot;remarquable&quot;] = 0
df.loc[df.remarquable == &quot;OUI&quot;, &quot;remarquable&quot;] = 1
</code></pre>
<p><strong>Pourquoi cette méthode ?</strong></p>
<ol>
<li><strong>Sémantique claire</strong> : 0 = absence de propriété, 1 = présence. Cette convention est universelle.</li>
<li><strong>Performance</strong> : Pas besoin d&#39;instancier un encodeur complexe pour deux valeurs.</li>
<li><strong>Interprétabilité</strong> : Dans un modèle de régression logistique, le coefficient associé aura une interprétation directe (impact sur le log-odds).</li>
</ol>
<p><strong>Analogie technique</strong> : C&#39;est l&#39;équivalent d&#39;un bit en informatique — un interrupteur qui ne peut être que OFF (0) ou ON (1).</p>
<h3>Avantages et Limites</h3>
<p>✅ <strong>Avantages</strong> :</p>
<ul>
<li>Simple et lisible</li>
<li>Aucune dépendance externe (pas besoin de bibliothèques spécialisées)</li>
<li>Économie de mémoire : un seul entier par ligne</li>
</ul>
<p>❌ <strong>Limites</strong> :</p>
<ul>
<li>Ne généralise pas aux variables avec plus de deux catégories</li>
<li>Nécessite une gestion manuelle des nouvelles données</li>
</ul>
<hr>
<h2>Technique 2 : Encodage Ordinal — La Variable <code>stade_de_developpement</code></h2>
<h3>Théorie des Variables Ordinales</h3>
<p>Une variable ordinale est une catégorie où <strong>l&#39;ordre relatif a une signification intrinsèque</strong>. Le stade de développement d&#39;un arbre suit une progression biologique naturelle :</p>
<pre><code>Ø (manquant) → Jeune → Jeune/Adulte → Adulte → Mature
</code></pre>
<p>Cette séquence est <strong>non interchangeable</strong> : un arbre ne peut pas être &quot;Mature&quot; avant d&#39;avoir été &quot;Jeune&quot;. C&#39;est différent d&#39;une variable nominale (espèce) où aucun ordre n&#39;existe.</p>
<p><strong>Analogie</strong> : Les niveaux scolaires (Maternelle → Primaire → Collège → Lycée) suivent une progression ordonnée. On ne peut pas être au lycée avant d&#39;avoir terminé le collège.</p>
<h3>Implémentation avec OrdinalEncoder</h3>
<p>L&#39;utilisation de <code>category_encoders.OrdinalEncoder</code> offre plusieurs avantages sur un mapping manuel :</p>
<pre><code class="language-python">from category_encoders.ordinal import OrdinalEncoder

mapping = [
    {
        &quot;col&quot;: &quot;stade_de_developpement&quot;,
        &quot;mapping&quot;: {
            np.nan: 0,              # Valeur manquante
            &quot;Jeune (arbre)&quot;: 1,
            &quot;Jeune (arbre)Adulte&quot;: 2,
            &quot;Adulte&quot;: 3,
            &quot;Mature&quot;: 4,
        },
    }
]

encoder = OrdinalEncoder(mapping=mapping)
stade = encoder.fit_transform(df[[&quot;stade_de_developpement&quot;]])
</code></pre>
<h3>Gestion des Valeurs Manquantes</h3>
<p>Un point critique : la présence de <code>np.nan</code> (valeurs manquantes). Dans ce dataset, certains arbres n&#39;ont pas de stade renseigné. L&#39;encodeur ordinal les mappe explicitement à <strong>0</strong>, ce qui permet :</p>
<ol>
<li><strong>Conservation des données</strong> : On ne perd pas les lignes incomplètes</li>
<li><strong>Distinction sémantique</strong> : 0 = &quot;information inconnue&quot;, différent de 1 = &quot;Jeune&quot;</li>
<li><strong>Compatibilité algorithmique</strong> : La plupart des algorithmes ML gèrent les 0, mais pas les <code>NaN</code></li>
</ol>
<p><strong>Bonnes pratiques</strong> :</p>
<ul>
<li>Toujours vérifier <code>value_counts(dropna=False)</code> avant et après encodage</li>
<li>Documenter explicitement la signification de la valeur 0</li>
<li>Envisager des stratégies alternatives (imputation par la médiane, modèle prédictif) si les valeurs manquantes représentent &gt;20% des données</li>
</ul>
<h3>Application au DataFrame</h3>
<p>Un piège classique pour les débutants est d&#39;oublier d&#39;intégrer l&#39;encodage au DataFrame original :</p>
<pre><code class="language-python"># ❌ Erreur : l&#39;encodage reste isolé
stade = encoder.fit_transform(df[[&quot;stade_de_developpement&quot;]])

# ✅ Correct : intégration au DataFrame
df[&quot;stade_de_developpement&quot;] = stade[&quot;stade_de_developpement&quot;].copy()
</code></pre>
<p><strong>Pourquoi <code>.copy()</code> ?</strong> Pour éviter les avertissements SettingWithCopyWarning de Pandas et garantir une copie mémoire indépendante.</p>
<p><strong>Analogie</strong> : Remplacer le moteur d&#39;une voiture. Ce n&#39;est pas suffisant de construire un nouveau moteur à côté ; il faut l&#39;installer dans le châssis pour que la voiture fonctionne.</p>
<hr>
<h2>Technique 3 : Encodage Binaire (Binary Encoding) — La Variable <code>espece</code></h2>
<h3>Le Défi des Variables Nominales à Haute Cardinalité</h3>
<p>La variable <code>espece</code> présente un problème différent : il n&#39;y a <strong>aucun ordre naturel</strong> entre un Platane, un Chêne ou un Érable. De plus, le dataset complet contient des dizaines voire centaines d&#39;espèces différentes (haute cardinalité).</p>
<h3>Pourquoi One-Hot Encoding N&#39;est Pas Optimal Ici</h3>
<p>La technique classique pour les variables nominales est le <strong>One-Hot Encoding</strong> :</p>
<ul>
<li>Chêne → <code>[1, 0, 0]</code></li>
<li>Érable → <code>[0, 1, 0]</code></li>
<li>Platane → <code>[0, 0, 1]</code></li>
</ul>
<p>Mais si on a <strong>100 espèces</strong>, cela crée <strong>100 colonnes</strong> dans le DataFrame, ce qui :</p>
<ol>
<li>Augmente drastiquement la dimensionnalité (curse of dimensionality)</li>
<li>Crée une matrice creuse (sparse matrix) coûteuse en mémoire</li>
<li>Ralentit l&#39;entraînement des modèles</li>
</ol>
<h3>Binary Encoding : La Solution Compacte</h3>
<p>Le <strong>Binary Encoding</strong> représente chaque catégorie en <strong>code binaire</strong>, comme en informatique :</p>
<pre><code class="language-python">Espèce A (1)   → [0, 0, 0, 1]
Espèce B (2)   → [0, 0, 1, 0]
Espèce C (3)   → [0, 0, 1, 1]
Espèce D (4)   → [0, 1, 0, 0]
...
Espèce 100 (100) → [1, 1, 0, 0, 1, 0, 0]  # 2^7 = 128 &gt; 100
</code></pre>
<p><strong>Avantage majeur</strong> : Pour encoder <strong>N</strong> catégories, on n&#39;a besoin que de <strong>log₂(N)</strong> colonnes.</p>
<ul>
<li>100 espèces → 7 colonnes (car 2⁷ = 128)</li>
<li>1000 espèces → 10 colonnes (car 2¹⁰ = 1024)</li>
</ul>
<p>Versus 100 ou 1000 colonnes avec One-Hot Encoding !</p>
<h3>Implémentation</h3>
<pre><code class="language-python">from category_encoders.binary import BinaryEncoder

encoder = BinaryEncoder()
espece_bin = encoder.fit_transform(data[[&quot;espece&quot;]])

print(f&quot;Shape: {espece_bin.shape}&quot;)
# Résultat : (207641, 10) → 10 colonnes pour toutes les espèces
</code></pre>
<p><strong>Note importante</strong> : Dans notre notebook, on applique l&#39;encodage sur <code>data</code> (dataset complet), pas sur <code>df</code> (uniquement les Platanes), car <code>df</code> ne contient qu&#39;une seule espèce. Encoder une seule catégorie n&#39;a aucun intérêt pratique — c&#39;est une démonstration technique.</p>
<h3>Analogie : Les Codes-Barres</h3>
<p>Un code-barres sur un produit de supermarché est composé de barres noires (1) et blanches (0). Il identifie <strong>uniquement</strong> le produit, sans suggérer qu&#39;un code 12345 est &quot;meilleur&quot; ou &quot;plus grand&quot; qu&#39;un code 67890. C&#39;est exactement ce que fait le Binary Encoding : identifier de manière unique sans créer de hiérarchie artificielle.</p>
<hr>
<h2>Tableau Récapitulatif : Quelle Technique Choisir ?</h2>
<table>
<thead>
<tr>
<th>Type de Variable</th>
<th>Exemple</th>
<th>Méthode Recommandée</th>
<th>Justification</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Binaire</strong></td>
<td>OUI/NON, Vrai/Faux</td>
<td>Encodage manuel (0/1)</td>
<td>Simple, sémantique claire, pas de dépendance</td>
</tr>
<tr>
<td><strong>Ordinale</strong></td>
<td>Jeune → Adulte → Mature</td>
<td>OrdinalEncoder</td>
<td>Préserve l&#39;ordre naturel, gestion des valeurs manquantes</td>
</tr>
<tr>
<td><strong>Nominale (peu de catégories &lt; 10)</strong></td>
<td>Couleurs (Rouge, Vert, Bleu)</td>
<td>One-Hot Encoding</td>
<td>Pas d&#39;ordre, nombre limité de colonnes créées</td>
</tr>
<tr>
<td><strong>Nominale (haute cardinalité &gt; 50)</strong></td>
<td>Espèces, Villes, Codes postaux</td>
<td>BinaryEncoder</td>
<td>Compact (log₂ colonnes), évite la matrice creuse, pas de hiérarchie</td>
</tr>
</tbody></table>
<hr>
<h2>Pièges Critiques à Éviter</h2>
<h3>1. Le Double Encodage</h3>
<p><strong>Erreur classique observée</strong> : Appliquer deux encodages successifs sur la même colonne.</p>
<pre><code class="language-python"># ❌ Double encodage (bug détecté dans la version initiale du notebook)
for category in df.stade_de_developpement.unique():
    df.loc[df.stade_de_developpement == category, &quot;stade_de_developpement&quot;] = code

encoder = OrdinalEncoder(mapping=mapping)
stade = encoder.fit_transform(df[[&quot;stade_de_developpement&quot;]])
</code></pre>
<p><strong>Symptôme</strong> : Résultats aberrants (valeurs -1.0 ou 0.0 uniquement) parce que l&#39;encodeur cherche les catégories textuelles originales, mais trouve des nombres déjà transformés.</p>
<p><strong>Solution</strong> : Supprimer l&#39;encodage manuel et n&#39;utiliser que <code>OrdinalEncoder</code>.</p>
<h3>2. Oublier l&#39;Intégration au DataFrame</h3>
<pre><code class="language-python"># ❌ Erreur fréquente
espece_encoded = encoder.fit_transform(df[[&quot;espece&quot;]])
# df contient toujours du texte ! Le modèle ne verra jamais les valeurs numériques.

# ✅ Correction
espece_encoded = encoder.fit_transform(df[[&quot;espece&quot;]])
df = pd.concat([df, espece_encoded], axis=1)
df.drop(&quot;espece&quot;, axis=1, inplace=True)
</code></pre>
<p><strong>Règle d&#39;or</strong> : Toute variable transformée qui doit servir de feature dans un modèle ML <strong>DOIT être intégrée au DataFrame final</strong>. C&#39;est comme préparer une recette : on ne peut pas donner farine, œufs et sucre dans des bols séparés au four. Il faut tout mélanger dans un seul récipient.</p>
<h3>3. Créer une Hiérarchie Artificielle pour les Variables Nominales</h3>
<pre><code class="language-python"># ❌ Mauvaise pratique pour les espèces
df[&quot;espece&quot;] = df[&quot;espece&quot;].map({&quot;Chêne&quot;: 1, &quot;Érable&quot;: 2, &quot;Platane&quot;: 3})
</code></pre>
<p>Le modèle pourrait interpréter mathématiquement que <code>Platane (3) = Chêne (1) + Érable (2)</code>, ce qui n&#39;a aucun sens biologique.</p>
<p><strong>Solution</strong> : Utiliser One-Hot ou Binary Encoding pour les variables nominales.</p>
<hr>
<h2>Bonnes Pratiques Industrielles</h2>
<h3>Vérification Systématique Après Transformation</h3>
<p>Toujours inspecter les résultats avec <code>value_counts()</code> :</p>
<pre><code class="language-python">print(&quot;Avant encodage :&quot;)
print(df.stade_de_developpement.value_counts(dropna=False))

# ... encodage ...

print(&quot;Après encodage :&quot;)
print(df.stade_de_developpement.value_counts())
</code></pre>
<p>Cela permet de détecter immédiatement les anomalies (valeurs inattendues, perte de données).</p>
<h3>Sauvegarde des Encodeurs pour la Production</h3>
<p>En production, les nouvelles données doivent être encodées <strong>exactement de la même manière</strong> que les données d&#39;entraînement. Il faut donc sauvegarder les encodeurs :</p>
<pre><code class="language-python">import joblib

# Après entraînement
joblib.dump(encoder, &quot;ordinal_encoder_stade.pkl&quot;)

# En production
encoder = joblib.load(&quot;ordinal_encoder_stade.pkl&quot;)
new_data_encoded = encoder.transform(new_data[[&quot;stade_de_developpement&quot;]])
</code></pre>
<h3>Pipeline Scikit-Learn</h3>
<p>Pour éviter les oublis et garantir la reproductibilité, intégrer les encodeurs dans un pipeline :</p>
<pre><code class="language-python">from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestRegressor

pipeline = Pipeline([
    (&quot;encoder&quot;, OrdinalEncoder(mapping=mapping)),
    (&quot;model&quot;, RandomForestRegressor())
])

pipeline.fit(X_train, y_train)
# L&#39;encodage est automatiquement appliqué à chaque prédiction
predictions = pipeline.predict(X_test)
</code></pre>
<hr>
<h2>Cas Particulier : Pourquoi <code>espece</code> N&#39;Est Pas Appliquée à Notre DataFrame ?</h2>
<p>Dans notre notebook, l&#39;encodage de la variable <code>espece</code> est appliqué sur le dataset complet (<code>data</code>), mais <strong>pas intégré au DataFrame filtré <code>df</code></strong>. Pourquoi ?</p>
<p><strong>Raison pédagogique</strong> : <code>df</code> ne contient que des <strong>Platanes</strong> (une seule espèce). Encoder une seule catégorie créerait une colonne constante (toujours la même valeur), ce qui est :</p>
<ol>
<li><strong>Inutile pour le modèle</strong> : Aucune variance, aucune information discriminante</li>
<li><strong>Redondant</strong> : Le modèle apprendrait que cette colonne n&#39;apporte rien</li>
</ol>
<p>C&#39;est une <strong>démonstration technique</strong> de la méthode Binary Encoding sur le dataset complet (plusieurs espèces), mais pas une étape réelle de preprocessing pour notre sous-ensemble.</p>
<p><strong>Dans un projet réel</strong> avec plusieurs espèces dans <code>df</code>, il faudrait absolument appliquer l&#39;encodage et l&#39;intégrer au DataFrame.</p>
<hr>
<h2>Conclusion : L&#39;Art du Preprocessing Catégoriel</h2>
<p>Le choix de la technique d&#39;encodage catégoriel n&#39;est pas anodin. Il impacte directement :</p>
<ul>
<li><strong>La performance du modèle</strong> : Un mauvais encodage (hiérarchie artificielle) introduit du biais</li>
<li><strong>Le temps de calcul</strong> : La dimensionnalité excessive ralentit l&#39;entraînement</li>
<li><strong>L&#39;interprétabilité</strong> : Comprendre la signification des coefficients appris</li>
</ul>
<p>Les trois principes directeurs sont :</p>
<ol>
<li><strong>Respecter la nature de la variable</strong> : Binaire, ordinale ou nominale ?</li>
<li><strong>Économiser les dimensions</strong> : Préférer Binary Encoding à One-Hot pour la haute cardinalité</li>
<li><strong>Vérifier et valider</strong> : Toujours inspecter les distributions avant/après encodage</li>
</ol>
<p>Ce guide, basé sur un dataset réel de 42 588 arbres parisiens, fournit un framework décisionnel réutilisable pour tout projet de Data Science nécessitant le preprocessing de variables catégorielles.</p>
<hr>
<h2>Ressources Complémentaires</h2>
<h3>Bibliothèques Utilisées</h3>
<ul>
<li><strong><a href="https://contrib.scikit-learn.org/category_encoders/" target="_blank" rel="noopener noreferrer">Category Encoders</a></strong> : Bibliothèque complète d&#39;encodeurs (Ordinal, Binary, Target, etc.)</li>
<li><strong><a href="https://pandas.pydata.org/" target="_blank" rel="noopener noreferrer">Pandas</a></strong> : Manipulation de DataFrames</li>
<li><strong><a href="https://numpy.org/" target="_blank" rel="noopener noreferrer">NumPy</a></strong> : Opérations numériques et gestion des valeurs manquantes</li>
</ul>
<h3>Techniques Avancées Non Couvertes</h3>
<ul>
<li><strong>Target Encoding</strong> : Encoder une catégorie par la moyenne de la variable cible (risque de fuite de données)</li>
<li><strong>Frequency Encoding</strong> : Remplacer chaque catégorie par sa fréquence d&#39;apparition</li>
<li><strong>Embeddings</strong> : Représentation vectorielle apprise (utilisée en Deep Learning)</li>
</ul>
<h3>Dataset Source</h3>
<p>Le dataset des arbres de Paris est fourni par <a href="https://openclassrooms.com/" target="_blank" rel="noopener noreferrer">OpenClassrooms</a> dans le cadre du cours &quot;Initiez-vous au Machine Learning&quot;. Il contient plus de 200 000 observations avec des métadonnées sur l&#39;espèce, la localisation, les dimensions et l&#39;état sanitaire des arbres.</p>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Tue, 16 Dec 2025 10:21:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
    <item>
      <title><![CDATA[Guide pratique : Le Clustering avec K-means]]></title>
      <link>https://clement-reboul.fr/blog/guide-pratique-le-clustering-avec-k-means/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/guide-pratique-le-clustering-avec-k-means/</guid>
      <description><![CDATA[Ce guide explique le clustering (regroupement), une technique d'apprentissage automatique non supervisé qui permet de trouver des groupes naturels dans les données, sans avoir d'étiquettes au départ.]]></description>
      <content:encoded><![CDATA[<h2>Supervisé vs. Non Supervisé : La Grande Différence</h2>
<h3>Apprentissage Supervisé</h3>
<p>Dans la régression et la classification, nous avions toujours une variable cible (la &quot;réponse&quot;) :</p>
<ul>
<li>Régression: Prédire les ventes, le poids, le prix...</li>
<li>Classification : Prédire si une tumeur est maligne/bénigne, si un email est spam/non-spam...</li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme un professeur qui vous donne des exercices avec les réponses. Vous apprenez en voyant les bonnes réponses.</p>
<h3>Apprentissage Non Supervisé (le Clustering)</h3>
<p>Dans le <strong>clustering</strong>, il n&#39;y a <strong>pas de variable cible</strong>. L&#39;ordinateur doit trouver les groupes tout seul !</p>
<p><strong>Analogie</strong> : C&#39;est comme ranger des jouets dans des boîtes sans instructions. Vous devez décider vous-même quels jouets vont ensemble (les voitures ensemble, les poupées ensemble, les peluches ensemble...).</p>
<h3>Le Critère Fondamental : La Distance</h3>
<p><strong>Question clé</strong> : Sans variable cible, comment l&#39;ordinateur sait-il que deux éléments sont similaires ?</p>
<p><strong>Réponse</strong> : Il utilise uniquement la <strong>distance</strong> entre les échantillons !</p>
<ul>
<li><strong>Deux points proches</strong> (petite distance) → similaires → même groupe ✅</li>
<li><strong>Deux points éloignés</strong> (grande distance) → différents → groupes différents ❌</li>
</ul>
<p><strong>Analogie</strong> : Dans une soirée, les gens qui se connaissent se regroupent naturellement. Ils sont &quot;proches&quot; socialement. Le clustering fait la même chose avec des données, mais en mesurant la proximité avec une formule mathématique.</p>
<p>La distance utilisée est généralement la <strong>distance euclidienne</strong> (la distance &quot;à vol d&#39;oiseau&quot;, la plus courte).</p>
<p><strong>Formule</strong> : Pour deux points (x₁, y₁) et (x₂, y₂) :</p>
<pre><code>distance = √[(x₂ - x₁)² + (y₂ - y₁)²]
</code></pre>
<hr>
<h2>L&#39;Algorithme K-means : Comment ça Marche ?</h2>
<h3>Les Objectifs du K-means</h3>
<p>L&#39;algorithme k-means cherche à créer <strong>K groupes</strong> (clusters) avec deux objectifs :</p>
<ol>
<li><strong>Minimiser la distance à l&#39;intérieur d&#39;un groupe</strong> → groupes denses </li>
<li><strong>Maximiser la distance entre les groupes</strong> → groupes bien séparés</li>
</ol>
<p><strong>Analogie</strong> : C&#39;est comme organiser des tables dans une salle de classe :</p>
<ul>
<li>Les élèves d&#39;une même table doivent être proches les uns des autres (groupe dense)</li>
<li>Les tables doivent être éloignées les unes des autres (groupes séparés)</li>
</ul>
<h3>Le Processus Itératif : Les 2 Étapes qui se Répètent</h3>
<p>Le k-means est un <strong>processus itératif</strong> : il répète les mêmes actions plusieurs fois jusqu&#39;à trouver la meilleure solution.</p>
<h4>Étape 1 : Attribution des Données (Assignation)</h4>
<p><strong>Ce qui se passe</strong> :</p>
<ul>
<li>Chaque échantillon (chaque point) regarde tous les <strong>centroïdes</strong> (centres de groupe)</li>
<li>Il calcule la distance qui le sépare de chaque centroïde</li>
<li>Il est assigné au centroïde le <strong>plus proche</strong></li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme si chaque élève dans une classe s&#39;asseyait à la table dont le centre est le plus proche de lui. Si un élève est à 2 mètres de la table A et 5 mètres de la table B, il va vers la table A.</p>
<p><strong>En code</strong> :</p>
<pre><code class="language-python"># Pour chaque point, trouver le centroïde le plus proche
for point in data:
    distances = [distance(point, centroid) for centroid in centroids]
    point.cluster = argmin(distances)  # Assigner au plus proche
</code></pre>
<h4>Étape 2 : Mise à Jour des Centroïdes (Déplacement)</h4>
<p><strong>Ce qui se passe</strong> :</p>
<ul>
<li>Une fois que tous les points sont assignés, le centre de gravité (la <strong>moyenne</strong>) de chaque groupe est recalculé</li>
<li>Le centroïde se déplace à cette nouvelle position</li>
</ul>
<p><strong>Analogie</strong> : Imaginez que les centres de table peuvent se déplacer. Après que tous les élèves se soient assis, chaque centre de table se repositionne pour être exactement au milieu de tous les élèves qui y sont assis.</p>
<p><strong>En code</strong> :</p>
<pre><code class="language-python"># Recalculer la position de chaque centroïde
for cluster in clusters:
    points_in_cluster = get_points_in_cluster(cluster)
    new_centroid = mean(points_in_cluster)  # Moyenne de tous les points
    cluster.centroid = new_centroid
</code></pre>
<h3>La Convergence : Quand S&#39;Arrêter ?</h3>
<p>Ces deux étapes se répètent jusqu&#39;à ce que les <strong>centroïdes ne bougent presque plus</strong>.</p>
<p><strong>Pourquoi s&#39;arrêter quand les centroïdes ne bougent plus ?</strong></p>
<p>Parce que cela signifie que le modèle a trouvé une configuration <strong>stable</strong> :</p>
<ul>
<li>Chaque point est déjà assigné au centroïde le plus proche</li>
<li>Si on recalcule les centroïdes, ils tombent au même endroit</li>
<li>Les groupes sont <strong>cohérents</strong> et <strong>optimaux</strong></li>
</ul>
<p>On dit que l&#39;algorithme a <strong>convergé</strong>.</p>
<p><strong>Analogie</strong> : C&#39;est comme arrêter de réorganiser les meubles dans une pièce quand vous avez trouvé le meilleur agencement. Si vous bougez une chaise, vous la remettez au même endroit → c&#39;est stable.</p>
<h3>Illustration du Processus K-means</h3>
<p>Voici comment l&#39;algorithme k-means évolue étape par étape :</p>
<p><img src="https://user.oc-static.com/upload/2023/10/18/16976315555998_image8.png" alt="Processus K-means - Itérations"></p>
<p><strong>Ce que montre ce graphique</strong> :</p>
<ul>
<li><strong>Gauche</strong> : Initialisation avec centroïdes aléatoires</li>
<li><strong>Milieu</strong> : Après quelques itérations, les groupes commencent à se former</li>
<li><strong>Droite</strong> : Convergence finale - les groupes sont bien définis et stables</li>
</ul>
<p>Les couleurs représentent les différents clusters, et les étoiles (★) sont les centroïdes.</p>
<hr>
<h2>Évaluation du Clustering : Choisir le Bon K</h2>
<h3>Le Problème du Choix de K</h3>
<p>Le <strong>point faible</strong> du k-means : il faut choisir le nombre de clusters <strong>K</strong> à l&#39;avance !</p>
<ul>
<li>Si K = 2, on aura 2 groupes</li>
<li>Si K = 5, on aura 5 groupes</li>
<li>Mais quel est le <strong>bon</strong> K ?</li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme essayer de ranger des livres. Combien de piles devez-vous faire ? 3 piles (romans, BD, documentaires) ? 5 piles (en ajoutant policiers et science-fiction) ? Il faut trouver le nombre qui a le plus de sens.</p>
<h3>Le Coefficient de Silhouette</h3>
<p>Le <strong>Coefficient de Silhouette</strong> est un score qui évalue la qualité des groupes en tenant compte de deux critères :</p>
<ol>
<li><strong>Densité du groupe</strong> : Les points sont-ils proches dans leur groupe ?</li>
<li><strong>Séparation du groupe</strong> : Les groupes sont-ils éloignés des autres ?</li>
</ol>
<p><strong>Échelle du Coefficient de Silhouette</strong> :</p>
<table>
<thead>
<tr>
<th>Score</th>
<th>Interprétation</th>
</tr>
</thead>
<tbody><tr>
<td><strong>+1</strong></td>
<td>Clustering parfait ✅ (groupes très denses et très bien séparés)</td>
</tr>
<tr>
<td><strong>0</strong></td>
<td>Clustering ambigu ⚠️ (les groupes se chevauchent)</td>
</tr>
<tr>
<td><strong>-1</strong></td>
<td>Très mauvais clustering ❌ (points assignés au mauvais groupe)</td>
</tr>
</tbody></table>
<p><strong>Formule simplifiée</strong> :</p>
<pre><code>Silhouette = (distance au groupe le plus proche - distance moyenne dans son groupe)
             / max(les deux distances)
</code></pre>
<h3>Comment Trouver le K Optimal ?</h3>
<p><strong>Méthode</strong> :</p>
<ol>
<li><p><strong>Essais Multiples</strong> : Entraîner le modèle avec différentes valeurs de K</p>
<ul>
<li>Essayer K=2, K=3, K=4... jusqu&#39;à K=10</li>
</ul>
</li>
<li><p><strong>Calcul du Score</strong> : Pour chaque K, calculer le Coefficient de Silhouette</p>
</li>
<li><p><strong>Observation Graphique</strong> : Tracer l&#39;évolution du score</p>
</li>
<li><p><strong>Choisir le Maximum</strong> : Le K qui donne le score le plus élevé (le <strong>pic</strong>) est le meilleur</p>
</li>
</ol>
<p><strong>Exemple de graphique</strong> :</p>
<p><img src="https://user.oc-static.com/upload/2023/10/18/16976317595078_image49.png" alt="Coefficient de Silhouette en fonction de K"></p>
<p><strong>Lecture du graphique</strong> :</p>
<ul>
<li>L&#39;axe horizontal montre le nombre de clusters (K)</li>
<li>L&#39;axe vertical montre le score de Silhouette</li>
<li>Le <strong>pic</strong> indique le meilleur K</li>
</ul>
<p>Dans cet exemple, <strong>K=3</strong> est optimal car il donne le meilleur score (≈0.60).</p>
<p><strong>Interprétation</strong> :</p>
<ul>
<li>K=3 donne le meilleur compromis entre groupes denses et bien séparés</li>
<li>K=2 : pas assez de groupes, on mélange des choses différentes</li>
<li>K=7 : trop de groupes, on divise des choses similaires</li>
</ul>
<hr>
<h2>Application : Le Dataset Iris</h2>
<h3>Présentation du Dataset</h3>
<p>Le <strong>dataset Iris</strong> est un classique du machine learning :</p>
<ul>
<li>150 échantillons de fleurs</li>
<li>3 familles : <strong>Setosa</strong>, <strong>Versicolor</strong>, <strong>Virginica</strong></li>
<li>4 caractéristiques : longueur/largeur des pétales et sépales</li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme avoir 150 fleurs de 3 espèces différentes et mesurer la taille de leurs pétales et feuilles. Le défi : peut-on regrouper les fleurs similaires sans connaître leur espèce ?</p>
<h3>Application du K-means</h3>
<p><strong>Paramètres</strong> :</p>
<ul>
<li>K = 3 clusters (on demande 3 groupes)</li>
<li>Résultat : Coefficient de Silhouette = 0.55</li>
</ul>
<p><strong>Qu&#39;est-ce que 0.55 signifie ?</strong></p>
<p>Rappelons l&#39;échelle :</p>
<ul>
<li>1 = parfait</li>
<li>0 = ambigu</li>
<li>-1 = mauvais</li>
</ul>
<p><strong>0.55 est à mi-chemin entre 0 et 1</strong>, ce qui indique :</p>
<ul>
<li>✅ Le clustering a <strong>plutôt bien réussi</strong></li>
<li>✅ Les groupes sont <strong>cohérents</strong> et <strong>bien séparés</strong></li>
<li>⚠️ Ce n&#39;est pas parfait, il y a un peu de chevauchement</li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme obtenir 11/20 à un examen. Ce n&#39;est pas excellent, mais c&#39;est correct et au-dessus de la moyenne.</p>
<h3>Comparaison avec les Vraies Familles</h3>
<p><strong>Question intéressante</strong> : Les 3 groupes trouvés par le k-means correspondent-ils aux 3 vraies familles de fleurs ?</p>
<p>Pour le savoir, on compare :</p>
<ul>
<li><strong>Clusters trouvés</strong> par k-means (Cluster 0, 1, 2)</li>
<li><strong>Vraies familles</strong> du dataset (Setosa, Versicolor, Virginica)</li>
</ul>
<p><strong>Résultat : Accuracy = 88.7%</strong></p>
<p><strong>Qu&#39;est-ce que 88.7% signifie ?</strong></p>
<p>Cela signifie que le k-means a réussi à regrouper <strong>88.7% des fleurs</strong> dans des clusters qui correspondent exactement à leurs vraies familles, <strong>sans jamais avoir vu les noms des familles</strong> pendant l&#39;entraînement !</p>
<p><strong>C&#39;est impressionnant car</strong> :</p>
<ul>
<li>L&#39;algorithme n&#39;avait que les mesures physiques (longueur/largeur)</li>
<li>Il n&#39;avait aucune information sur les espèces</li>
<li>Pourtant, il a retrouvé les groupes naturels avec 88.7% de précision</li>
</ul>
<p><strong>Analogie</strong> : C&#39;est comme si on vous demandait de trier 150 photos de chiens en 3 piles (Berger Allemand, Golden Retriever, Chihuahua) sans vous dire les races. Vous devez juste observer les ressemblances. Si vous réussissez à 88.7%, c&#39;est excellent !</p>
<hr>
<h2>Analyse de la Matrice de Confusion 🔍</h2>
<p>Puisque 88.7% est une bonne performance, regardons les <strong>11.3% d&#39;erreurs</strong> (17 fleurs mal classées).</p>
<h3>La Matrice de Confusion</h3>
<p><img src="https://user.oc-static.com/upload/2023/10/20/16978057269426_P2C4-3.png" alt="Matrice de Confusion - Dataset Iris"></p>
<table>
<thead>
<tr>
<th></th>
<th><strong>Prédit Cluster 0</strong></th>
<th><strong>Prédit Cluster 1</strong></th>
<th><strong>Prédit Cluster 2</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Vraie Famille 0</strong></td>
<td><strong>50</strong> ✅</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>Vraie Famille 1</strong></td>
<td>0</td>
<td><strong>47</strong> ✅</td>
<td>3 ❌</td>
</tr>
<tr>
<td><strong>Vraie Famille 2</strong></td>
<td>0</td>
<td>14 ❌</td>
<td><strong>36</strong> ✅</td>
</tr>
</tbody></table>
<p><strong>Lecture de la matrice</strong> :</p>
<ul>
<li><strong>Diagonale</strong> (50, 47, 36) : fleurs correctement regroupées ✅</li>
<li><strong>Hors diagonale</strong> (3, 14) : erreurs de regroupement ❌</li>
</ul>
<h3>Analyse Détaillée</h3>
<h4>Famille 0 (Setosa) : Perfection !</h4>
<pre><code>Vraie Famille 0 : 50 → Cluster 0
                   0 → Cluster 1
                   0 → Cluster 2
</code></pre>
<p><strong>Interprétation</strong> :</p>
<ul>
<li>Toutes les 50 fleurs Setosa ont été correctement groupées</li>
<li><strong>0 erreur</strong> : aucune confusion avec les autres familles</li>
<li>Score : <strong>100%</strong> pour cette famille</li>
</ul>
<p><strong>Qu&#39;est-ce que cela signifie ?</strong></p>
<p>Les fleurs Setosa ont des caractéristiques <strong>très distinctes</strong> des deux autres familles. Elles forment un nuage de points bien séparé.</p>
<p><strong>Analogie</strong> : C&#39;est comme avoir des Chihuahuas (très petits) parmi des Golden Retrievers et Bergers Allemands (grands). Le Chihuahua est tellement différent qu&#39;il est facile à identifier.</p>
<h4>Famille 1 (Versicolor) : Bon Résultat ✅</h4>
<pre><code>Vraie Famille 1 : 0  → Cluster 0
                  47 → Cluster 1  ✅
                   3 → Cluster 2  ❌
</code></pre>
<p><strong>Interprétation</strong> :</p>
<ul>
<li>47 fleurs sur 50 correctement groupées (94%)</li>
<li>3 fleurs confondues avec la Famille 2</li>
</ul>
<h4>Famille 2 (Virginica) : Le Plus d&#39;Erreurs ⚠️</h4>
<pre><code>Vraie Famille 2 : 0  → Cluster 0
                  14 → Cluster 1  ❌ ← Plus grande erreur !
                  36 → Cluster 2  ✅
</code></pre>
<p><strong>Interprétation</strong> :</p>
<ul>
<li>36 fleurs sur 50 correctement groupées (72%)</li>
<li><strong>14 fleurs</strong> confondues avec la Famille 1</li>
</ul>
<h3>Les Conclusions de l&#39;Analyse</h3>
<p><strong>Observation 1 : Famille 0 Facile à Séparer</strong></p>
<ul>
<li>Setosa est <strong>très distincte</strong> → 100% de réussite</li>
<li>Ses caractéristiques (longueur/largeur) sont très différentes</li>
</ul>
<p><strong>Observation 2 : Familles 1 et 2 Se Chevauchent</strong></p>
<ul>
<li>Versicolor et Virginica ont des caractéristiques <strong>similaires</strong></li>
<li>14 + 3 = 17 erreurs entre ces deux familles</li>
<li>C&#39;est la preuve que leurs pétales/sépales ont des tailles proches</li>
</ul>
<p><strong>Analogie</strong> :</p>
<ul>
<li>Setosa = Chihuahua (facile à distinguer)</li>
<li>Versicolor et Virginica = Golden Retriever vs Labrador Retriever (plus difficile car ils se ressemblent beaucoup)</li>
</ul>
<p><strong>Visualisation des clusters Iris</strong> :</p>
<p><img src="https://user.oc-static.com/upload/2023/10/18/16976323409325_image48.png" alt="Clusters K-means sur Iris"></p>
<p><strong>Ce que montre ce graphique</strong> :</p>
<ul>
<li>Chaque couleur représente un cluster trouvé par k-means</li>
<li>On voit clairement que le cluster violet (Setosa) est bien séparé</li>
<li>Les clusters orange et vert (Versicolor et Virginica) se chevauchent partiellement</li>
</ul>
<hr>
<h2>Récapitulatif : Les Points Clés</h2>
<h3>Ce qu&#39;est le Clustering</h3>
<table>
<thead>
<tr>
<th><strong>Apprentissage Supervisé</strong></th>
<th><strong>Apprentissage Non Supervisé (Clustering)</strong></th>
</tr>
</thead>
<tbody><tr>
<td>On a une variable cible</td>
<td>❌ Pas de variable cible</td>
</tr>
<tr>
<td>On apprend avec les réponses</td>
<td>On trouve les groupes soi-même</td>
</tr>
<tr>
<td>Régression, Classification</td>
<td>K-means, Clustering Hiérarchique</td>
</tr>
</tbody></table>
<h3>Comment Fonctionne le K-means</h3>
<ol>
<li><strong>Initialisation</strong> : Choisir K centroïdes au hasard</li>
<li><strong>Itération</strong> :<ul>
<li><strong>Étape 1</strong> : Assigner chaque point au centroïde le plus proche (distance)</li>
<li><strong>Étape 2</strong> : Recalculer les centroïdes (moyenne des points assignés)</li>
</ul>
</li>
<li><strong>Convergence</strong> : Répéter jusqu&#39;à ce que les centroïdes ne bougent plus</li>
</ol>
<h3>Comment Choisir K</h3>
<ol>
<li>Essayer plusieurs valeurs de K (2, 3, 4...)</li>
<li>Calculer le Coefficient de Silhouette pour chaque K</li>
<li>Choisir le K qui donne le <strong>score maximum</strong> (pic de la courbe)</li>
</ol>
<h3>Comment Évaluer la Qualité</h3>
<table>
<thead>
<tr>
<th><strong>Métrique</strong></th>
<th><strong>Interprétation</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Coefficient de Silhouette</strong></td>
<td>-1 (mauvais) à +1 (excellent)</td>
</tr>
<tr>
<td><strong>Accuracy</strong></td>
<td>Comparaison avec vraies classes (si disponibles)</td>
</tr>
<tr>
<td><strong>Matrice de Confusion</strong></td>
<td>Voir où sont les erreurs</td>
</tr>
</tbody></table>
<hr>
<h2>Cas d&#39;Usage du Clustering</h2>
<h3>Segmentation de Clients</h3>
<ul>
<li>Regrouper les clients par comportement d&#39;achat</li>
<li>Créer des campagnes marketing ciblées</li>
</ul>
<h3>Compression d&#39;Images</h3>
<ul>
<li>Réduire le nombre de couleurs en groupant les pixels similaires</li>
<li>K-means pour la quantification des couleurs</li>
</ul>
<h3>Détection d&#39;Anomalies</h3>
<ul>
<li>Trouver des points isolés (pas dans aucun cluster dense)</li>
<li>Détecter des fraudes, des pannes machines</li>
</ul>
<h3>Organisation de Documents</h3>
<ul>
<li>Regrouper des articles par thème</li>
<li>Créer des catégories automatiquement</li>
</ul>
<h3>Biologie</h3>
<ul>
<li>Classifier des espèces selon leurs caractéristiques</li>
<li>Exemple : Iris avec ses 3 familles</li>
</ul>
<hr>
<h2>Limites du K-means</h2>
<h3>1. Il faut choisir K à l&#39;avance</h3>
<ul>
<li>Pas toujours évident de savoir combien de groupes existent</li>
<li>Solution : Tester plusieurs K et utiliser le Coefficient de Silhouette</li>
</ul>
<h3>2. Sensible à l&#39;initialisation</h3>
<ul>
<li>Les centroïdes de départ sont aléatoires</li>
<li>Peut donner des résultats légèrement différents</li>
<li>Solution : Relancer plusieurs fois et garder le meilleur</li>
</ul>
<h3>3. Suppose des groupes sphériques</h3>
<ul>
<li>K-means fonctionne mieux avec des groupes ronds</li>
<li>Peut mal fonctionner avec des formes allongées ou complexes</li>
</ul>
<h3>4. Sensible aux valeurs extrêmes</h3>
<ul>
<li>Un point très éloigné peut déplacer un centroïde</li>
<li>Solution : Normaliser les données avant le clustering</li>
</ul>
<hr>
<h2>Pour Aller Plus Loin</h2>
<h3>Autres Algorithmes de Clustering</h3>
<ul>
<li><strong>DBSCAN</strong> : Ne nécessite pas de choisir K, trouve des formes complexes</li>
<li><strong>Clustering Hiérarchique</strong> : Crée un arbre de groupes (dendrogramme)</li>
<li><strong>GMM (Gaussian Mixture Models)</strong> : Version probabiliste du k-means</li>
</ul>
<h3>Optimisations du K-means</h3>
<ul>
<li><strong>K-means++</strong> : Meilleure initialisation des centroïdes</li>
<li><strong>Mini-batch K-means</strong> : Plus rapide pour de gros datasets</li>
</ul>
<h3>Visualisation</h3>
<ul>
<li><strong>PCA</strong> (Analyse en Composantes Principales) : Réduire à 2D pour visualiser</li>
<li><strong>t-SNE</strong> : Visualisation avancée de clusters en haute dimension</li>
</ul>
<hr>
<h2>Conclusion</h2>
<p>Le <strong>clustering</strong> est une technique puissante pour découvrir des structures cachées dans les données. Le <strong>k-means</strong> est l&#39;algorithme le plus populaire car il est :</p>
<p>✅ Simple à comprendre<br>✅ Rapide à exécuter<br>✅ Efficace pour de nombreux cas d&#39;usage</p>
<p>Son seul inconvénient : il faut choisir K. Mais avec le <strong>Coefficient de Silhouette</strong>, on peut trouver le K optimal !</p>
<p><strong>L&#39;exemple d&#39;Iris</strong> montre que le k-means peut retrouver des groupes naturels (les 3 espèces de fleurs) avec 88.7% de précision, juste en analysant les mesures physiques. C&#39;est la magie de l&#39;apprentissage non supervisé ! 🌸✨</p>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Sun, 14 Dec 2025 22:03:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
    <item>
      <title><![CDATA[Guide pratique : Classification avec la Régression Logistique]]></title>
      <link>https://clement-reboul.fr/blog/guide-pratique-classification-avec-la-regression-logistique/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/guide-pratique-classification-avec-la-regression-logistique/</guid>
      <description><![CDATA[Que faire si on veut classer des éléments dans des catégories plutôt que prédire un chiffre ?
Exemple : Déterminer si un email est un SPAM ou non, si une transaction est frauduleuse, si une tumeur est maligne...

C'est là qu'intervient la Classification !]]></description>
      <content:encoded><![CDATA[<h2>Régression vs Classification</h2>
<h3>Différence fondamentale</h3>
<table>
<thead>
<tr>
<th>Type</th>
<th>Objectif</th>
<th>Sortie</th>
<th>Exemple</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Régression</strong></td>
<td>Prédire un nombre</td>
<td>Valeur continue (n&#39;importe quel chiffre)</td>
<td>Prix : 250 000€</td>
</tr>
<tr>
<td><strong>Classification</strong></td>
<td>Classer dans une catégorie</td>
<td>Catégorie discrète (étiquette)</td>
<td>Spam : OUI ou NON</td>
</tr>
</tbody></table>
<p><strong>Analogie</strong> :</p>
<ul>
<li><strong>Régression</strong> = Donner une note sur 100 à un devoir</li>
<li><strong>Classification</strong> = Dire si l&#39;élève a réussi (A/B/C/D/F)</li>
</ul>
<hr>
<h2>Les Types de Classification</h2>
<h3>Classification Binaire ⚪⚫</h3>
<p><strong>Définition</strong> : Seulement <strong>2 catégories</strong> possibles.</p>
<p><strong>Exemples</strong> :</p>
<ul>
<li>Transaction : Fraude / Normale</li>
<li>Email : Spam / Légitime</li>
<li>Tumeur : Maligne / Bénigne</li>
<li>Diagnostic : Malade / Sain</li>
</ul>
<p><strong>Représentation</strong> : 0 ou 1, Vrai ou Faux, Oui ou Non</p>
<h3>Classification Multiclasse 🔴🔵🟢</h3>
<p><strong>Définition</strong> : Plus de <strong>2 catégories</strong> différentes.</p>
<p><strong>Exemples</strong> :</p>
<ul>
<li>Classifier des photos : Chien / Chat / Oiseau</li>
<li>Note d&#39;un film : ⭐ / ⭐⭐ / ⭐⭐⭐ / ⭐⭐⭐⭐ / ⭐⭐⭐⭐⭐</li>
<li>Type de fleur : Iris / Rose / Tulipe</li>
</ul>
<h3>Classification Multilabel 🏷️🏷️</h3>
<p><strong>Définition</strong> : Un objet peut appartenir à <strong>plusieurs catégories simultanément</strong>.</p>
<p><strong>Exemples</strong> :</p>
<ul>
<li>Film : &quot;Action&quot; ET &quot;Comédie&quot; ET &quot;Science-Fiction&quot;</li>
<li>Article de presse : &quot;Politique&quot; ET &quot;Économie&quot;</li>
<li>Maladie : Un patient peut avoir plusieurs pathologies</li>
</ul>
<h3>Catégories Ordinales vs Nominales</h3>
<p><strong>Ordinales</strong> : Il existe un <strong>ordre</strong> entre les catégories</p>
<ul>
<li>Mauvais &lt; Moyen &lt; Bon &lt; Excellent</li>
<li>Petite &lt; Moyenne &lt; Grande taille</li>
</ul>
<p><strong>Nominales</strong> : <strong>Pas d&#39;ordre</strong> naturel</p>
<ul>
<li>Couleurs : Rouge, Bleu, Vert</li>
<li>Pays : France, Japon, Brésil</li>
</ul>
<hr>
<h2>La Régression Logistique : Le Pont entre Régression et Classification</h2>
<h3>Pourquoi &quot;Régression&quot; pour faire de la &quot;Classification&quot; ? 🤔</h3>
<p>Le nom est trompeur ! La régression logistique <strong>utilise</strong> une régression pour <strong>faire</strong> de la classification.</p>
<h3>Le Processus en 3 Étapes</h3>
<h4>Étape 1 : Régression Linéaire Classique</h4>
<p>On commence comme avec la régression linéaire :</p>
<pre><code>y = a × x₁ + b × x₂ + c × x₃ + d
</code></pre>
<p><strong>Problème</strong> : <code>y</code> peut être <strong>n&#39;importe quel nombre</strong> (-∞ à +∞)</p>
<ul>
<li>Si y = 150 → Que faire ?</li>
<li>Si y = -50 → Ça n&#39;a pas de sens pour une catégorie !</li>
</ul>
<h4>Étape 2 : Fonction Logistique (Sigmoïde)</h4>
<p>On applique la <strong>fonction sigmoïde</strong> pour transformer <code>y</code> en probabilité <code>z</code> :</p>
<pre><code>z = 1 / (1 + e^(-y))
</code></pre>
<p><strong>Résultat</strong> : <code>z</code> est <strong>toujours entre 0 et 1</strong> → c&#39;est une <strong>probabilité</strong> !</p>
<p><strong>Graphique de la fonction sigmoïde</strong> :</p>
<pre><code>  1 |         ________
    |        /
z   |       /
    |      /
  0 |_____/____________
      -∞   0   +∞
           y
</code></pre>
<p><strong>Propriétés magiques</strong> :</p>
<ul>
<li>Si y = -∞ → z ≈ 0 (impossible)</li>
<li>Si y = 0 → z = 0.5 (50% de chances)</li>
<li>Si y = +∞ → z ≈ 1 (certain)</li>
</ul>
<h4>Étape 3 : Seuil de Classification</h4>
<p>On transforme la probabilité en décision ferme :</p>
<pre><code class="language-python">if z &gt;= 0.5:
    prédiction = 1  # Classe Positive
else:
    prédiction = 0  # Classe Négative
</code></pre>
<p><strong>Exemple concret</strong> :</p>
<ul>
<li>Probabilité de spam = 0.78 (78%) → <strong>SPAM</strong> ✅</li>
<li>Probabilité de spam = 0.23 (23%) → <strong>LÉGITIME</strong> ✅</li>
</ul>
<hr>
<h2>Évaluer la Performance : L&#39;Exactitude</h2>
<h3>L&#39;Exactitude (Accuracy)</h3>
<p><strong>C&#39;est quoi ?</strong> Le pourcentage de prédictions correctes.</p>
<p><strong>Formule</strong> :</p>
<pre><code>Exactitude = Nombre de bonnes prédictions / Nombre total de prédictions
</code></pre>
<p><strong>Exemple</strong> :</p>
<ul>
<li>100 emails testés</li>
<li>95 bien classés (spam ou légitime)</li>
<li><strong>Exactitude = 95%</strong> 🎉</li>
</ul>
<h3>Le Paradoxe de l&#39;Exactitude 😱</h3>
<p><strong>Problème</strong> : L&#39;exactitude peut être <strong>trompeuse</strong> !</p>
<p><strong>Exemple de la Fraude Bancaire</strong> :</p>
<ul>
<li>Dans 100 transactions, seulement <strong>1 est frauduleuse</strong> (1%)</li>
<li>Un modèle stupide qui dit <strong>TOUJOURS &quot;Pas de fraude&quot;</strong> aura :<ul>
<li>99 bonnes prédictions (les 99 légitimes)</li>
<li>1 erreur (la fraude non détectée)</li>
<li><strong>Exactitude = 99%</strong> 😮</li>
</ul>
</li>
</ul>
<p><strong>Conclusion</strong> : Ce modèle est <strong>inutile</strong> car il ne détecte <strong>aucune fraude</strong>, mais il a un score &quot;excellent&quot; !</p>
<p>C&#39;est pourquoi on a besoin d&#39;outils plus fins...</p>
<hr>
<h2>La Matrice de Confusion : Le Détective des Erreurs</h2>
<h3>Qu&#39;est-ce que c&#39;est ?</h3>
<p>Un tableau 2×2 qui croise <strong>Réalité</strong> vs <strong>Prédiction</strong> pour voir les 4 résultats possibles.</p>
<h3>Les 4 Résultats Possibles</h3>
<table>
<thead>
<tr>
<th></th>
<th><strong>Prédiction : Positif</strong></th>
<th><strong>Prédiction : Négatif</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Réalité : Positif</strong></td>
<td>✅ <strong>Vrai Positif (TP)</strong></td>
<td>❌ <strong>Faux Négatif (FN)</strong></td>
</tr>
<tr>
<td><strong>Réalité : Négatif</strong></td>
<td>❌ <strong>Faux Positif (FP)</strong></td>
<td>✅ <strong>Vrai Négatif (TN)</strong></td>
</tr>
</tbody></table>
<h3>Explications avec Exemples</h3>
<h4>✅ Vrai Positif (TP - True Positive)</h4>
<ul>
<li><strong>Réalité</strong> : Malade</li>
<li><strong>Prédiction</strong> : Malade</li>
<li><strong>Résultat</strong> : Bien détecté ! 👍</li>
</ul>
<h4>✅ Vrai Négatif (TN - True Negative)</h4>
<ul>
<li><strong>Réalité</strong> : Sain</li>
<li><strong>Prédiction</strong> : Sain</li>
<li><strong>Résultat</strong> : Bien ignoré ! 👍</li>
</ul>
<h4>❌ Faux Positif (FP - False Positive)</h4>
<ul>
<li><strong>Réalité</strong> : Sain</li>
<li><strong>Prédiction</strong> : Malade</li>
<li><strong>Résultat</strong> : <strong>Fausse alerte</strong> ! 🚨 (Alarme inutile)</li>
</ul>
<p><strong>Exemple</strong> : Email légitime envoyé dans les spams</p>
<h4>❌ Faux Négatif (FN - False Negative)</h4>
<ul>
<li><strong>Réalité</strong> : Malade</li>
<li><strong>Prédiction</strong> : Sain</li>
<li><strong>Résultat</strong> : <strong>Cas manqué</strong> ! 😰 (Danger non détecté)</li>
</ul>
<p><strong>Exemple</strong> : Maladie non diagnostiquée</p>
<h3>Quelle est l&#39;Erreur la Plus Grave ? 🚨</h3>
<p><strong>Dans le contexte médical</strong> : Le <strong>Faux Négatif (FN)</strong> est <strong>catastrophique</strong> !</p>
<ul>
<li>Le patient est malade mais le modèle dit qu&#39;il est sain</li>
<li>La maladie n&#39;est pas traitée → Conséquences potentiellement <strong>fatales</strong></li>
</ul>
<p><strong>Dans le contexte du spam</strong> : Le <strong>Faux Positif (FP)</strong> est plus gênant</p>
<ul>
<li>Un email important est classé comme spam</li>
<li>Risque de manquer une information cruciale</li>
</ul>
<hr>
<h2>Le Rappel (Recall) : Ne Rien Manquer</h2>
<h3>Définition</h3>
<p>Le <strong>Rappel</strong> mesure la capacité du modèle à <strong>détecter tous les cas positifs</strong>.</p>
<p><strong>Question clé</strong> : Parmi tous les malades réels, combien ai-je détectés ?</p>
<h3>Formule</h3>
<pre><code>Rappel = TP / (TP + FN)
</code></pre>
<p><strong>Décryptage du dénominateur</strong> :</p>
<ul>
<li><code>TP</code> = Vrais Positifs (bien détectés)</li>
<li><code>FN</code> = Faux Négatifs (malades manqués)</li>
<li><code>TP + FN</code> = <strong>TOUS les cas réellement positifs</strong> dans les données</li>
</ul>
<h3>Exemple Concret</h3>
<p><strong>Contexte</strong> : Détection de cancer, 100 patients, 20 sont malades</p>
<table>
<thead>
<tr>
<th>Résultat</th>
<th>Nombre</th>
</tr>
</thead>
<tbody><tr>
<td>Vrais Positifs (TP)</td>
<td>18 (détectés)</td>
</tr>
<tr>
<td>Faux Négatifs (FN)</td>
<td>2 (manqués)</td>
</tr>
<tr>
<td>Total de malades réels</td>
<td>20</td>
</tr>
</tbody></table>
<p><strong>Calcul</strong> :</p>
<pre><code>Rappel = 18 / (18 + 2) = 18 / 20 = 0.90 = 90%
</code></pre>
<p><strong>Interprétation</strong> : Le modèle détecte <strong>90% des malades</strong>, mais en manque <strong>10%</strong> (2 personnes).</p>
<h3>Quand privilégier le Rappel ?</h3>
<p>✅ <strong>Situations critiques</strong> où manquer un cas est <strong>dangereux</strong> :</p>
<ul>
<li>Détection de maladies graves</li>
<li>Détection de fraudes financières</li>
<li>Détection d&#39;intrusions informatiques</li>
<li>Contrôle qualité (défauts de fabrication)</li>
</ul>
<p><strong>Objectif</strong> : <strong>NE RIEN MANQUER</strong>, même si ça génère des fausses alertes.</p>
<hr>
<h2>La Précision (Precision) : Éviter les Fausses Alertes</h2>
<h3>Définition</h3>
<p>La <strong>Précision</strong> mesure la <strong>fiabilité</strong> des alertes du modèle.</p>
<p><strong>Question clé</strong> : Parmi toutes mes alertes positives, combien étaient vraies ?</p>
<h3>Formule</h3>
<pre><code>Précision = TP / (TP + FP)
</code></pre>
<p><strong>Décryptage du dénominateur</strong> :</p>
<ul>
<li><code>TP</code> = Vrais Positifs (alertes correctes)</li>
<li><code>FP</code> = Faux Positifs (fausses alertes)</li>
<li><code>TP + FP</code> = <strong>TOUTES les fois où le modèle a dit &quot;Positif&quot;</strong></li>
</ul>
<h3>Exemple Concret</h3>
<p><strong>Contexte</strong> : Filtre anti-spam, 1000 emails</p>
<table>
<thead>
<tr>
<th>Résultat</th>
<th>Nombre</th>
</tr>
</thead>
<tbody><tr>
<td>Vrais Positifs (TP)</td>
<td>180 (vrais spams détectés)</td>
</tr>
<tr>
<td>Faux Positifs (FP)</td>
<td>20 (emails légitimes classés spam)</td>
</tr>
<tr>
<td>Total d&#39;alertes spam</td>
<td>200</td>
</tr>
</tbody></table>
<p><strong>Calcul</strong> :</p>
<pre><code>Précision = 180 / (180 + 20) = 180 / 200 = 0.90 = 90%
</code></pre>
<p><strong>Interprétation</strong> : Quand le filtre dit &quot;SPAM&quot;, il a raison <strong>90% du temps</strong>, mais se trompe <strong>10% du temps</strong> (20 emails légitimes perdus).</p>
<h3>Quand privilégier la Précision ?</h3>
<p>✅ <strong>Situations où les fausses alertes sont coûteuses</strong> :</p>
<ul>
<li>Filtre anti-spam (ne pas perdre d&#39;emails importants)</li>
<li>Système de recommandation (ne pas recommander n&#39;importe quoi)</li>
<li>Publicité ciblée (ne pas gaspiller le budget sur les mauvaises cibles)</li>
</ul>
<p><strong>Objectif</strong> : <strong>Être SÛR de ses alertes</strong>, même si on en rate quelques-unes.</p>
<hr>
<h2>Le Compromis Précision / Rappel</h2>
<h3>Le Dilemme</h3>
<p><strong>Problème</strong> : On ne peut pas maximiser les deux en même temps ! 😰</p>
<h3>Scénario 1 : Modèle Ultra-Prudent (Précision Élevée)</h3>
<p><strong>Comportement</strong> : Le modèle ne dit &quot;Positif&quot; que quand il est <strong>TRÈS SÛR</strong>.</p>
<p><strong>Conséquences</strong> :</p>
<ul>
<li>✅ <strong>Précision élevée</strong> : Peu de fausses alertes (FP↓)</li>
<li>❌ <strong>Rappel faible</strong> : Beaucoup de cas manqués (FN↑)</li>
</ul>
<p><strong>Analogie</strong> : Un détecteur de fumée qui ne sonne que si la maison est en flammes</p>
<ul>
<li>Pas de fausses alarmes ✅</li>
<li>Mais il rate les petits débuts d&#39;incendie ❌</li>
</ul>
<h3>Scénario 2 : Modèle Ultra-Sensible (Rappel Élevé)</h3>
<p><strong>Comportement</strong> : Le modèle dit &quot;Positif&quot; au moindre <strong>doute</strong>.</p>
<p><strong>Conséquences</strong> :</p>
<ul>
<li>✅ <strong>Rappel élevé</strong> : Peu de cas manqués (FN↓)</li>
<li>❌ <strong>Précision faible</strong> : Beaucoup de fausses alertes (FP↑)</li>
</ul>
<p><strong>Analogie</strong> : Un détecteur de fumée ultra-sensible</p>
<ul>
<li>Il détecte tout ✅</li>
<li>Mais il sonne pour un toast brûlé ❌</li>
</ul>
<h3>Le Rôle du Seuil de Classification</h3>
<p><strong>Rappel</strong> : On transforme la probabilité en décision avec un seuil (par défaut 0.5).</p>
<pre><code class="language-python">if probabilité &gt;= seuil:
    prédiction = Positif
else:
    prédiction = Négatif
</code></pre>
<h4>Baisser le Seuil (ex: 0.3)</h4>
<pre><code class="language-python">if probabilité &gt;= 0.3:  # Plus facile de dire &quot;Positif&quot;
    prédiction = Positif
</code></pre>
<p><strong>Effet</strong> :</p>
<ul>
<li>📈 <strong>Rappel augmente</strong> (on détecte plus de positifs)</li>
<li>📉 <strong>Précision diminue</strong> (plus de fausses alertes)</li>
</ul>
<h4>Augmenter le Seuil (ex: 0.7)</h4>
<pre><code class="language-python">if probabilité &gt;= 0.7:  # Plus difficile de dire &quot;Positif&quot;
    prédiction = Positif
</code></pre>
<p><strong>Effet</strong> :</p>
<ul>
<li>📉 <strong>Rappel diminue</strong> (on manque plus de positifs)</li>
<li>📈 <strong>Précision augmente</strong> (moins de fausses alertes)</li>
</ul>
<h3>Tableau Récapitulatif (Détection Cancer du Sein)</h3>
<table>
<thead>
<tr>
<th>Seuil</th>
<th>Précision</th>
<th>Rappel</th>
<th>Interprétation</th>
</tr>
</thead>
<tbody><tr>
<td>0.3</td>
<td>92.86%</td>
<td><strong>98.32%</strong></td>
<td>Modèle sensible : détecte presque tout, quelques fausses alertes</td>
</tr>
<tr>
<td>0.5</td>
<td>95.00%</td>
<td>96.00%</td>
<td>Équilibré</td>
</tr>
<tr>
<td>0.7</td>
<td><strong>96.58%</strong></td>
<td>94.96%</td>
<td>Modèle prudent : alertes très fiables, rate quelques cas</td>
</tr>
</tbody></table>
<hr>
<h2>La Courbe ROC et l&#39;AUC : Vue Globale</h2>
<h3>Problème</h3>
<p>Comment évaluer un modèle <strong>indépendamment du seuil</strong> choisi ?</p>
<h3>La Courbe ROC (Receiver Operating Characteristic)</h3>
<p><strong>Principe</strong> : Tracer le graphique du Rappel vs Taux de Faux Positifs pour <strong>tous les seuils possibles</strong>.</p>
<p><img src="https://support.minitab.com/fr-fr/minitab/media/generated-content/images/bctree_example_ROC.PNG" alt="Courbe ROC"></p>
<p><strong>Axes</strong> :</p>
<ul>
<li><strong>Axe Y</strong> : TPR (True Positive Rate) = Rappel = TP / (TP + FN)</li>
<li><strong>Axe X</strong> : FPR (False Positive Rate) = FP / (FP + TN)</li>
</ul>
<pre><code>  1 |    📈
    |   /|
TPR |  / |   ← Courbe du modèle
    | /  |
  0 |/_____|_____
    0    0.5    1
         FPR
</code></pre>
<h3>Interprétation de la Courbe</h3>
<h4>Modèle Aléatoire (AUC = 0.5)</h4>
<pre><code>  1 |
    |    /
TPR |   /    ← Diagonale = Tirage au sort
    |  /
  0 |/_________
    0         1
       FPR
</code></pre>
<p><strong>Signification</strong> : Le modèle est <strong>aussi bon qu&#39;une pièce de monnaie</strong> 🪙</p>
<ul>
<li>Performance équivalente au hasard</li>
<li><strong>Inutile</strong> !</li>
</ul>
<h4>Modèle Parfait (AUC = 1.0)</h4>
<pre><code>  1 |_____
    |    |
TPR |    |    ← Coin supérieur gauche
    |    |
  0 |____|_____
    0         1
       FPR
</code></pre>
<p><strong>Signification</strong> :</p>
<ul>
<li>TPR = 100% (tous les positifs détectés)</li>
<li>FPR = 0% (aucune fausse alerte)</li>
<li><strong>Modèle idéal</strong> ! 🏆</li>
</ul>
<h4>Modèle Réaliste (AUC = 0.85)</h4>
<pre><code>  1 |    ___
    |   /  |
TPR |  /   |
    | /    |
  0 |/_____|___
    0         1
       FPR
</code></pre>
<p><strong>Signification</strong> : Bon modèle, mais pas parfait</p>
<ul>
<li>Compromis entre détection et fausses alertes</li>
</ul>
<h3>L&#39;AUC (Area Under the Curve)</h3>
<p><strong>Définition</strong> : La <strong>surface sous la courbe ROC</strong>.</p>
<p><strong>Échelle d&#39;interprétation</strong> :</p>
<table>
<thead>
<tr>
<th>AUC</th>
<th>Qualité du Modèle</th>
<th>Interprétation</th>
</tr>
</thead>
<tbody><tr>
<td>0.5</td>
<td>💀 Aléatoire</td>
<td>Aussi bon qu&#39;une pièce</td>
</tr>
<tr>
<td>0.6-0.7</td>
<td>😐 Faible</td>
<td>Peu fiable</td>
</tr>
<tr>
<td>0.7-0.8</td>
<td>👍 Acceptable</td>
<td>Utilisable</td>
</tr>
<tr>
<td>0.8-0.9</td>
<td>🎯 Bon</td>
<td>Très performant</td>
</tr>
<tr>
<td>0.9-1.0</td>
<td>🏆 Excellent</td>
<td>Modèle de production</td>
</tr>
<tr>
<td>1.0</td>
<td>🦄 Parfait</td>
<td>Probablement surapprentissage !</td>
</tr>
</tbody></table>
<p><strong>Avantage</strong> : Métrique <strong>unique</strong> qui résume la performance sur <strong>tous les seuils</strong>.</p>
<hr>
<h2>Résumé : Quand Utiliser Quelle Métrique ?</h2>
<h3>Tableau de Décision</h3>
<table>
<thead>
<tr>
<th>Situation</th>
<th>Métrique à Privilégier</th>
<th>Raison</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Détection de maladie grave</strong></td>
<td>🎯 <strong>Rappel</strong></td>
<td>Manquer un malade est catastrophique</td>
</tr>
<tr>
<td><strong>Filtre anti-spam</strong></td>
<td>🔍 <strong>Précision</strong></td>
<td>Perdre un email important est problématique</td>
</tr>
<tr>
<td><strong>Détection de fraude</strong></td>
<td>🎯 <strong>Rappel</strong></td>
<td>Ne pas détecter une fraude coûte cher</td>
</tr>
<tr>
<td><strong>Recommandation de produits</strong></td>
<td>🔍 <strong>Précision</strong></td>
<td>Recommander n&#39;importe quoi énerve l&#39;utilisateur</td>
</tr>
<tr>
<td><strong>Évaluation générale</strong></td>
<td>📊 <strong>AUC</strong></td>
<td>Vision globale indépendante du seuil</td>
</tr>
<tr>
<td><strong>Dataset équilibré</strong></td>
<td>✅ <strong>Exactitude</strong></td>
<td>Quand les classes sont représentées équitablement</td>
</tr>
</tbody></table>
<hr>
<h2>🎓 Concepts Clés à Retenir</h2>
<h3>1. Régression Logistique</h3>
<p>✅ Utilise une régression linéaire + fonction sigmoïde<br>✅ Donne une <strong>probabilité</strong> entre 0 et 1<br>✅ Transformée en décision via un <strong>seuil</strong> (par défaut 0.5)</p>
<h3>2. Matrice de Confusion</h3>
<p>✅ <strong>TP</strong> : Vrai Positif (bien détecté)<br>✅ <strong>TN</strong> : Vrai Négatif (bien ignoré)<br>❌ <strong>FP</strong> : Faux Positif (fausse alerte)<br>❌ <strong>FN</strong> : Faux Négatif (cas manqué)</p>
<h3>3. Métriques</h3>
<p>✅ <strong>Exactitude</strong> : % de bonnes prédictions (attention au paradoxe !)<br>✅ <strong>Rappel</strong> : TP / (TP + FN) → Détecter tous les positifs<br>✅ <strong>Précision</strong> : TP / (TP + FP) → Fiabilité des alertes<br>✅ <strong>AUC</strong> : Surface sous courbe ROC → Évaluation globale</p>
<h3>4. Compromis Précision/Rappel</h3>
<p>✅ On ne peut pas maximiser les deux en même temps<br>✅ Le seuil permet d&#39;ajuster le compromis<br>✅ Choix dépend du contexte métier</p>
<hr>
<h2>💡 Analogies pour Bien Comprendre</h2>
<h3>Le Détecteur de Fumée</h3>
<p><strong>Rappel</strong> = Détecteur ultra-sensible</p>
<ul>
<li>✅ Détecte TOUS les incendies (même petits)</li>
<li>❌ Sonne pour un toast brûlé (fausses alertes)</li>
</ul>
<p><strong>Précision</strong> = Détecteur prudent</p>
<ul>
<li>✅ Ne sonne que pour les vrais incendies</li>
<li>❌ Rate les petits débuts de feu</li>
</ul>
<h3>Le Contrôle de Sécurité à l&#39;Aéroport</h3>
<p><strong>Rappel</strong> = Fouiller tout le monde systématiquement</p>
<ul>
<li>✅ Aucun danger ne passe</li>
<li>❌ Files d&#39;attente interminables</li>
</ul>
<p><strong>Précision</strong> = Fouiller seulement les suspects évidents</p>
<ul>
<li>✅ Flux rapide, peu de personnes embêtées</li>
<li>❌ Risque de laisser passer un danger</li>
</ul>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Sat, 13 Dec 2025 09:22:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
    <item>
      <title><![CDATA[Guide Pratique : Régression Linéaire sur le Dataset Advertising]]></title>
      <link>https://clement-reboul.fr/blog/guide-pratique-regression-lineaire-sur-le-dataset-advertising/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/guide-pratique-regression-lineaire-sur-le-dataset-advertising/</guid>
      <description><![CDATA[Ce guide vous accompagne pas à pas dans l'analyse du dataset Advertising pour prédire les ventes en fonction des budgets publicitaires (TV, radio, journaux).
]]></description>
      <content:encoded><![CDATA[<h2>📚 Introduction</h2>
<p>Ce guide vous accompagne pas à pas dans l&#39;analyse du dataset <strong>Advertising</strong> pour prédire les <strong>ventes</strong> en fonction des budgets publicitaires (TV, radio, journaux).</p>
<p><a href="https://github.com/OpenClassrooms-Student-Center/8063076-Initiez-vous-au-Machine-Learning/blob/master/data/age_vs_poids_vs_taille_vs_sexe.csv" target="_blank" rel="noopener noreferrer">Télécharger le fichier CSV</a></p>
<p><strong>Objectif</strong> : Comprendre comment construire un modèle de régression linéaire, l&#39;évaluer, et l&#39;améliorer avec des techniques simples.</p>
<hr>
<h2>Comprendre les données</h2>
<h3>Le dataset Advertising</h3>
<p><strong>200 observations</strong> avec 4 variables :</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody><tr>
<td><strong>tv</strong></td>
<td>Budget pub TV (milliers €)</td>
<td>Variable prédictive</td>
</tr>
<tr>
<td><strong>radio</strong></td>
<td>Budget pub radio (milliers €)</td>
<td>Variable prédictive</td>
</tr>
<tr>
<td><strong>journaux</strong></td>
<td>Budget pub journaux (milliers €)</td>
<td>Variable prédictive</td>
</tr>
<tr>
<td><strong>ventes</strong></td>
<td>Volume de ventes</td>
<td><strong>Variable cible</strong> (ce qu&#39;on veut prédire)</td>
</tr>
</tbody></table>
<h3>Première exploration</h3>
<pre><code class="language-python">import pandas as pd

df = pd.read_csv(&quot;advertising.csv&quot;)
print(df.head())
print(df.describe())
</code></pre>
<p><strong>Ce qu&#39;on observe</strong> :</p>
<ul>
<li>Moyenne TV : ~147, Radio : ~23, Journaux : ~31</li>
<li>Ventes moyennes : ~14</li>
<li>Aucune valeur manquante ✅</li>
</ul>
<hr>
<h2>Visualiser les relations</h2>
<h3>Pourquoi visualiser ?</h3>
<p>Avant de construire un modèle, il faut <strong>voir</strong> si les variables sont liées aux ventes.</p>
<h3>Les graphiques avec trendline (ligne de régression)</h3>
<pre><code class="language-python">import plotly.express as px

fig = px.scatter(df, x=&quot;tv&quot;, y=&quot;ventes&quot;,
                 trendline=&quot;ols&quot;,  # Ordinary Least Squares
                 title=&quot;TV vs Ventes&quot;)
fig.show()
</code></pre>
<p><strong>Ce que montre le paramètre <code>trendline=&quot;ols&quot;</code></strong> :</p>
<ul>
<li>Trace automatiquement la <strong>meilleure droite</strong> qui passe au plus près des points</li>
<li>OLS = méthode mathématique pour trouver cette droite</li>
<li>Si les points sont proches de la ligne → forte relation 💪</li>
<li>Si les points sont dispersés → faible relation 😐</li>
</ul>
<h3>Les corrélations</h3>
<table>
<thead>
<tr>
<th>Variables</th>
<th>Corrélation avec ventes</th>
</tr>
</thead>
<tbody><tr>
<td><strong>tv</strong></td>
<td>0.78 🔥 (très forte)</td>
</tr>
<tr>
<td><strong>radio</strong></td>
<td>0.58 👍 (forte)</td>
</tr>
<tr>
<td><strong>journaux</strong></td>
<td>0.23 😐 (faible)</td>
</tr>
</tbody></table>
<p><strong>Interprétation simple</strong> :</p>
<ul>
<li><strong>0.78</strong> : Quand le budget TV augmente, les ventes augmentent beaucoup</li>
<li><strong>0.23</strong> : Les journaux ont peu d&#39;impact sur les ventes</li>
</ul>
<hr>
<h2>Construire le modèle de régression linéaire</h2>
<h3>Qu&#39;est-ce qu&#39;une régression linéaire ?</h3>
<p>C&#39;est trouver la formule mathématique qui relie les variables :</p>
<pre><code>ventes = a × tv + b × radio + c × journaux + d
</code></pre>
<p>Le modèle va chercher les meilleurs coefficients <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code> pour prédire au mieux les ventes.</p>
<h3>Le code</h3>
<pre><code class="language-python">from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# 1. Préparer les données
X = df[[&quot;tv&quot;, &quot;radio&quot;, &quot;journaux&quot;]]  # Variables prédictives
y = df.ventes                        # Variable cible

# 2. Séparer en train (80%) et test (20%)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.20, random_state=42
)

# 3. Créer et entraîner le modèle
reg = LinearRegression()
reg.fit(X_train, y_train)  # Le modèle &quot;apprend&quot;

# 4. Faire des prédictions
y_pred_test = reg.predict(X_test)
</code></pre>
<h3>🧠 Comprendre train_test_split</h3>
<p><strong>Pourquoi séparer les données ?</strong></p>
<p>Imaginez que vous préparez un examen :</p>
<ul>
<li><strong>Train (80%)</strong> = Les exercices que vous faites pour apprendre</li>
<li><strong>Test (20%)</strong> = L&#39;examen final avec des questions que vous n&#39;avez jamais vues</li>
</ul>
<p>Si vous testez sur les mêmes données que l&#39;entraînement, vous trichez ! Le modèle connaît déjà les réponses.</p>
<p><strong>Le paramètre <code>random_state=42</code></strong> :</p>
<ul>
<li>Assure que la séparation est toujours la même</li>
<li>Permet de reproduire les résultats</li>
<li>Sans ça, chaque exécution donnerait des résultats différents</li>
</ul>
<hr>
<h2>Évaluer le modèle</h2>
<h3>Les métriques d&#39;évaluation</h3>
<pre><code class="language-python">from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error

rmse = mean_squared_error(y_test, y_pred_test)
mape = mean_absolute_percentage_error(y_test, y_pred_test)

print(f&quot;RMSE : {rmse}&quot;)
print(f&quot;MAPE : {mape}&quot;)
</code></pre>
<h3>📏 RMSE (Root Mean Square Error)</h3>
<p><strong>C&#39;est quoi ?</strong> L&#39;erreur moyenne de vos prédictions.</p>
<p><strong>Exemple concret</strong> :</p>
<ul>
<li>Si RMSE = 3.17</li>
<li>En moyenne, vos prédictions se trompent de <strong>±3.17 unités de ventes</strong></li>
<li>Si les vraies ventes sont 15, vous prédisez entre 11.83 et 18.17</li>
</ul>
<p><strong>Caractéristique</strong> : Pénalise fortement les grosses erreurs</p>
<ul>
<li>Se tromper de 10 compte plus que se tromper de 1 dix fois</li>
</ul>
<h3>🎯 MAPE (Mean Absolute Percentage Error)</h3>
<p><strong>C&#39;est quoi ?</strong> L&#39;erreur en <strong>pourcentage</strong>.</p>
<p><strong>Exemple concret</strong> :</p>
<ul>
<li>Si MAPE = 0.15 (soit 15%)</li>
<li>En moyenne, vos prédictions ont <strong>15% d&#39;erreur</strong></li>
<li>Si les vraies ventes sont 100, vous prédisez entre 85 et 115</li>
</ul>
<p><strong>Avantage</strong> : Plus intuitif et comparable entre différents projets</p>
<h3>Est-ce bon ou mauvais ?</h3>
<p>Pour le modèle simple :</p>
<ul>
<li>RMSE ≈ 3.17 → Pas mal 👍</li>
<li>MAPE ≈ 0.15 (15%) → Correct mais peut mieux faire 🤔</li>
</ul>
<hr>
<h2>Amélioration : La régression polynomiale</h2>
<h3>Le problème détecté</h3>
<p>En regardant le graphique TV vs Ventes, on remarque que les points forment une <strong>courbe</strong> plutôt qu&#39;une ligne droite.</p>
<p><strong>Exemple visuel</strong> :</p>
<pre><code>Budget TV faible (0-50)    → Les ventes augmentent lentement
Budget TV moyen (100-150)  → Les ventes augmentent normalement
Budget TV élevé (200-300)  → Les ventes augmentent rapidement
</code></pre>
<p>C&#39;est une <strong>accélération</strong> = relation <strong>non-linéaire</strong> !</p>
<h3>La solution : ajouter tv²</h3>
<p>Au lieu de :</p>
<pre><code>ventes = a × tv + ...
</code></pre>
<p>On fait :</p>
<pre><code>ventes = a × tv + b × tv² + ...
</code></pre>
<h3>Pourquoi tv² capture la courbure ?</h3>
<p><strong>Exemple simple</strong> :</p>
<table>
<thead>
<tr>
<th>tv</th>
<th>tv²</th>
<th>Rapport</th>
</tr>
</thead>
<tbody><tr>
<td>10</td>
<td>100</td>
<td>-</td>
</tr>
<tr>
<td>20</td>
<td>400</td>
<td>×4 (pas ×2 !)</td>
</tr>
<tr>
<td>30</td>
<td>900</td>
<td>×9 (pas ×3 !)</td>
</tr>
</tbody></table>
<p>Le terme <code>tv²</code> augmente <strong>beaucoup plus vite</strong> que <code>tv</code>, ce qui crée l&#39;effet de courbure/accélération.</p>
<hr>
<h2>Normalisation : Pourquoi et comment ?</h2>
<h3>Le problème d&#39;échelle</h3>
<p>Après avoir créé <code>tv²</code>, on a :</p>
<ul>
<li><code>tv</code> : entre 0 et 300</li>
<li><code>tv²</code> : entre 0 et <strong>90 000</strong> ! 😱</li>
</ul>
<p>Le modèle va penser que <code>tv²</code> est beaucoup plus important juste parce que les chiffres sont gros.</p>
<h3>La solution : MinMaxScaler</h3>
<p><strong>Ce que ça fait</strong> : Ramène toutes les variables entre 0 et 1.</p>
<p><strong>Exemple</strong> :</p>
<pre><code>Avant :
tv = [0, 100, 200, 300]

Après normalisation :
tv = [0, 0.33, 0.66, 1.0]
</code></pre>
<h3>Le code</h3>
<pre><code class="language-python">from sklearn.preprocessing import MinMaxScaler

# 1. Créer tv²
df[&#39;tv2&#39;] = df.tv ** 2

# 2. Normaliser
scaler = MinMaxScaler()
data_normalized = scaler.fit_transform(df)
df_normalized = pd.DataFrame(data_normalized,
                              columns=[&#39;tv&#39;, &#39;radio&#39;, &#39;journaux&#39;, &#39;ventes&#39;, &#39;tv2&#39;])

# 3. Entraîner avec tv²
X_poly = df_normalized[[&#39;tv&#39;, &#39;radio&#39;, &#39;journaux&#39;, &#39;tv2&#39;]]
y_poly = df_normalized.ventes

X_train, X_test, y_train, y_test = train_test_split(
    X_poly, y_poly, test_size=0.20, random_state=42
)

reg_poly = LinearRegression()
reg_poly.fit(X_train, y_train)
y_pred_poly = reg_poly.predict(X_test)
</code></pre>
<h3>Comprendre fit_transform</h3>
<p><strong>Les 4 étapes du scaler</strong> :</p>
<ol>
<li><p><strong><code>fit()</code></strong> : Le scaler regarde les données et calcule :</p>
<ul>
<li>Le minimum de chaque colonne</li>
<li>Le maximum de chaque colonne</li>
</ul>
</li>
<li><p><strong><code>transform()</code></strong> : Le scaler applique la formule :</p>
<pre><code>valeur_normalisée = (valeur - min) / (max - min)
</code></pre>
</li>
<li><p><strong><code>fit_transform()</code></strong> : Fait les 2 étapes d&#39;un coup (plus rapide)</p>
</li>
</ol>
<p><strong>Exemple concret</strong> :</p>
<pre><code class="language-python">tv = [0, 100, 200, 300]

# Le scaler calcule :
min = 0
max = 300

# Puis transforme :
0   → (0 - 0) / 300 = 0
100 → (100 - 0) / 300 = 0.33
200 → (200 - 0) / 300 = 0.66
300 → (300 - 0) / 300 = 1.0
</code></pre>
<hr>
<h2>Comparaison des résultats</h2>
<h3>Tableau récapitulatif</h3>
<table>
<thead>
<tr>
<th>Modèle</th>
<th>Variables utilisées</th>
<th>RMSE</th>
<th>MAPE</th>
<th>Amélioration</th>
</tr>
</thead>
<tbody><tr>
<td>Linéaire simple</td>
<td>tv, radio, journaux</td>
<td>~3.17</td>
<td>~0.15</td>
<td>-</td>
</tr>
<tr>
<td>Polynomiale</td>
<td>tv, radio, journaux, <strong>tv²</strong></td>
<td><strong>Plus petit</strong></td>
<td><strong>Plus petit</strong></td>
<td>✅ Meilleur</td>
</tr>
</tbody></table>
<h3>Pourquoi c&#39;est mieux ?</h3>
<p>Le terme quadratique <code>tv²</code> permet de capturer la <strong>vraie relation</strong> entre TV et ventes :</p>
<ul>
<li>Pas juste une ligne droite</li>
<li>Mais une <strong>courbe</strong> qui représente l&#39;accélération des ventes avec le budget</li>
</ul>
<hr>
<h2>Convention de nommage importante</h2>
<h3>La notation <code>_pred</code></h3>
<p>En machine learning, on utilise cette convention :</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Signification</th>
</tr>
</thead>
<tbody><tr>
<td><code>y_test</code></td>
<td>Les <strong>vraies</strong> valeurs de ventes</td>
</tr>
<tr>
<td><code>y_pred_test</code></td>
<td>Les valeurs <strong>prédites</strong> par le modèle</td>
</tr>
</tbody></table>
<p><strong>Pourquoi c&#39;est important ?</strong></p>
<ul>
<li>Distingue clairement la <strong>réalité</strong> des <strong>prédictions</strong></li>
<li>Évite les confusions dans le code</li>
<li>Standard dans toute la communauté ML</li>
</ul>
<p><strong>Analogie</strong> :</p>
<ul>
<li><code>y_test</code> = Les bonnes réponses de l&#39;examen</li>
<li><code>y_pred_test</code> = Vos réponses (ce que le modèle pense)</li>
<li>Les métriques (RMSE, MAPE) = La note de l&#39;examen (comparaison des deux)</li>
</ul>
<hr>
<h2>🎓 Concepts clés à retenir</h2>
<h3>1. Train/Test Split</h3>
<p>✅ <strong>Toujours</strong> séparer les données<br>✅ Typiquement 80/20 ou 70/30<br>✅ Le modèle n&#39;a <strong>jamais vu</strong> les données de test</p>
<h3>2. Corrélation</h3>
<p>✅ Entre -1 et +1<br>✅ Plus proche de ±1 = plus forte relation<br>✅ Proche de 0 = pas de relation</p>
<h3>3. Régression polynomiale</h3>
<p>✅ Ajouter des puissances (x²) capture les courbes<br>✅ Plus flexible que la régression linéaire simple<br>✅ Attention à ne pas &quot;sur-complexifier&quot; (overfitting)</p>
<h3>4. Normalisation</h3>
<p>✅ Met toutes les variables sur la même échelle<br>✅ Permet de comparer l&#39;importance des coefficients<br>✅ Évite que les grandes valeurs dominent</p>
<h3>5. Métriques d&#39;évaluation</h3>
<p>✅ <strong>RMSE</strong> : Erreur absolue, pénalise les grosses erreurs<br>✅ <strong>MAPE</strong> : Erreur en %, facile à interpréter<br>✅ Plus petit = meilleur modèle</p>
<hr>
<h2>🚀 Pour aller plus loin</h2>
<h3>Idées d&#39;améliorations</h3>
<ol>
<li><p><strong>Ajouter des termes croisés</strong> : <code>tv × radio</code></p>
<ul>
<li>Capture l&#39;effet combiné de campagnes multi-canal</li>
</ul>
</li>
<li><p><strong>Retirer la variable <code>journaux</code></strong></p>
<ul>
<li>Corrélation faible (0.23), peut simplifier le modèle</li>
</ul>
</li>
<li><p><strong>Tester d&#39;autres modèles</strong></p>
<ul>
<li>Random Forest, Gradient Boosting</li>
<li>Comparer les performances</li>
</ul>
</li>
<li><p><strong>Analyser les résidus</strong></p>
<ul>
<li>Différence entre prédiction et réalité</li>
<li>Identifier les patterns d&#39;erreurs</li>
</ul>
</li>
</ol>
<hr>
<h2>📝 Résumé du workflow complet</h2>
<pre><code>1. Charger les données
   ↓
2. Explorer (head, describe, visualisations)
   ↓
3. Analyser les corrélations
   ↓
4. Préparer X (variables) et y (cible)
   ↓
5. Split train/test
   ↓
6. Entraîner le modèle (fit)
   ↓
7. Prédire (predict)
   ↓
8. Évaluer (RMSE, MAPE)
   ↓
9. Améliorer (ajouter tv², normaliser)
   ↓
10. Comparer les résultats
</code></pre>
<hr>
<h2>💡 Analogies pour bien comprendre</h2>
<h3>Le modèle = Un étudiant</h3>
<ul>
<li><strong>fit()</strong> = Réviser avec les exercices du livre</li>
<li><strong>predict()</strong> = Passer l&#39;examen</li>
<li><strong>Train set</strong> = Les exercices du livre</li>
<li><strong>Test set</strong> = L&#39;examen avec de nouvelles questions</li>
<li><strong>RMSE/MAPE</strong> = La note de l&#39;examen</li>
</ul>
<h3>La régression linéaire = Tracer une droite</h3>
<ul>
<li>On a des points sur un graphique</li>
<li>On cherche la meilleure droite qui passe près de tous les points</li>
<li>Les coefficients = La pente et la hauteur de la droite</li>
<li>L&#39;erreur = La distance moyenne entre les points et la droite</li>
</ul>
<h3>La normalisation = Mettre tout en euros</h3>
<ul>
<li>Sans normalisation : comparer des pommes (2€) et des voitures (20 000€)</li>
<li>Avec normalisation : tout entre 0 et 1, on compare des proportions</li>
<li>Comme mettre toutes les valeurs en &quot;pourcentage du maximum&quot;</li>
</ul>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Thu, 11 Dec 2025 19:34:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
    <item>
      <title><![CDATA[Évaluer la Performance d'un Modèle Prédictif]]></title>
      <link>https://clement-reboul.fr/blog/evaluer-la-performance-d-un-modele-predictif/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/evaluer-la-performance-d-un-modele-predictif/</guid>
      <description><![CDATA[Pour développer un système d'intelligence artificielle fiable, il ne suffit pas d'entraîner un modèle : il faut surtout être capable de mesurer objectivement sa performance. Cette étape cruciale garantit que votre modèle fait des prédictions précises et utiles.]]></description>
      <content:encoded><![CDATA[<p>L&#39;évaluation d&#39;un modèle de Machine Learning est une étape cruciale qui permet de mesurer sa capacité à faire des prédictions fiables. Dans cet article, nous allons explorer les concepts fondamentaux de l&#39;évaluation de performance à travers un exemple concret de régression linéaire.</p>
<h2>Un exemple pratique : prédire le poids d&#39;enfants</h2>
<p>Imaginons un dataset contenant 237 échantillons d&#39;enfants âgés de 11,5 à 20 ans, avec les informations suivantes :</p>
<ul>
<li><strong>L&#39;âge</strong> (exprimé en mois, de 139 à 250 mois)</li>
<li><strong>Le sexe</strong> (variable binaire : 0 pour les garçons, 1 pour les filles)</li>
<li><strong>La taille</strong> (entre 128,27 cm et 182,88 cm)</li>
<li><strong>Le poids</strong> (entre 22,9 kg et 77,78 kg)</li>
</ul>
<p>Notre objectif est de construire un modèle qui prédit le <strong>poids</strong> d&#39;un enfant en fonction de son sexe, son âge et sa taille.</p>
<h2>Le principe de la régression linéaire</h2>
<p>Le modèle que nous cherchons à construire s&#39;exprime mathématiquement comme :</p>
<p><strong>poids = a × sexe + b × age + c × taille + bruit</strong></p>
<p>Où :</p>
<ul>
<li><strong>a, b, c</strong> sont les coefficients que le modèle doit apprendre</li>
<li><strong>Le bruit</strong> représente l&#39;information que le modèle ne peut pas capturer</li>
</ul>
<p>Ce type de modèle, appelé <strong>régression linéaire</strong>, est l&#39;un des plus simples mais aussi des plus puissants en Machine Learning.</p>
<h2>Les trois étapes de l&#39;entraînement</h2>
<h3>Étape 1 : Charger et préparer les données</h3>
<p>La première étape consiste à organiser nos données :</p>
<ul>
<li><strong>X</strong> (la matrice de design) : contient les variables prédictives (âge, sexe, taille)</li>
<li><strong>y</strong> (le vecteur cible) : contient la variable à prédire (le poids)</li>
</ul>
<p>Par convention, <strong>X</strong> représente toujours les données d&#39;entrée où chaque ligne correspond à un échantillon et chaque colonne à une variable.</p>
<h3>Étape 2 : Entraîner le modèle</h3>
<p>L&#39;entraînement consiste à trouver les meilleurs coefficients <strong>a, b, c</strong> qui minimisent l&#39;écart entre les prédictions du modèle et les vraies valeurs. Cette phase est automatiquement gérée par les bibliothèques de Machine Learning comme scikit-learn.</p>
<h3>Étape 3 : Évaluer la performance</h3>
<p>Une fois le modèle entraîné, il faut mesurer sa qualité. C&#39;est là qu&#39;interviennent les <strong>métriques d&#39;évaluation</strong>.</p>
<h2>Les fonctions de coût : le moteur de l&#39;apprentissage</h2>
<p>Une <strong>fonction de coût</strong> mesure l&#39;écart entre les prédictions du modèle et les valeurs réelles. Le but de l&#39;entraînement est de <strong>minimiser</strong> cette fonction.</p>
<p>Pour la régression linéaire, la fonction de coût la plus courante est la <strong>MSE</strong> (Mean Squared Error - Erreur Quadratique Moyenne) :</p>
<p><strong>MSE = (1/N) × Σ(yₖ - ŷₖ)²</strong></p>
<p>Où :</p>
<ul>
<li><strong>N</strong> : le nombre d&#39;échantillons</li>
<li><strong>yₖ</strong> : les valeurs réelles</li>
<li><strong>ŷₖ</strong> : les valeurs prédites par le modèle</li>
</ul>
<h3>Comment ça marche ?</h3>
<p>Imaginez la fonction de coût comme une vallée. L&#39;algorithme d&#39;entraînement (comme la <strong>descente de gradient</strong>) explore cette vallée en calculant les dérivées pour trouver le chemin qui descend le plus rapidement vers le fond - c&#39;est-à-dire le minimum d&#39;erreur.</p>
<h2>Mesurer la performance : les métriques d&#39;évaluation</h2>
<p>Une fois le modèle entraîné, nous devons évaluer sa qualité sur de nouvelles données. Plusieurs métriques existent selon le type de problème.</p>
<h3>Pour les problèmes de régression</h3>
<p><strong>1. Le coefficient de détermination R²</strong></p>
<ul>
<li>Varie de 0 (mauvais) à 1 (parfait)</li>
<li>Mesure la proportion de variance expliquée par le modèle</li>
<li><strong>Plus il est proche de 1, meilleur est le modèle</strong></li>
</ul>
<p><strong>2. La RMSE (Root Mean Square Error)</strong></p>
<ul>
<li>Mesure l&#39;écart moyen entre prédictions et valeurs réelles</li>
<li>S&#39;exprime dans la même unité que la variable cible</li>
<li><strong>Plus elle est petite, meilleur est le modèle</strong></li>
</ul>
<p><strong>3. La MAE (Mean Absolute Error)</strong></p>
<ul>
<li>Erreur absolue moyenne</li>
<li>Moins sensible aux valeurs aberrantes que la RMSE</li>
<li><strong>Plus elle est petite, meilleur est le modèle</strong></li>
</ul>
<p><strong>4. La MAPE (Mean Absolute Percentage Error)</strong></p>
<ul>
<li>Exprime l&#39;erreur en pourcentage</li>
<li>Permet de comparer des modèles sur différents datasets</li>
<li><strong>Plus elle est petite, meilleur est le modèle</strong></li>
</ul>
<h3>Exemple de résultats</h3>
<p>Sur notre modèle prédisant le poids à partir du sexe et de l&#39;âge uniquement, nous obtenons :</p>
<ul>
<li><strong>RMSE</strong> : 45,17 kg</li>
<li><strong>MAE</strong> : 5,22 kg</li>
<li><strong>MAPE</strong> : 12%</li>
</ul>
<p>En ajoutant la variable <strong>taille</strong>, les scores s&#39;améliorent significativement, démontrant l&#39;importance de choisir les bonnes variables prédictives.</p>
<h2>Le processus complet d&#39;entraînement</h2>
<p>Voici la méthodologie à suivre pour tout projet de Machine Learning :</p>
<ol>
<li><strong>Charger les données</strong> : Importer et comprendre votre dataset</li>
<li><strong>Transformer les données</strong> : Nettoyer, normaliser, créer de nouvelles features</li>
<li><strong>Scinder en train/test</strong> : Séparer les données pour évaluer objectivement</li>
<li><strong>Entraîner le modèle</strong> : Tester différentes configurations de paramètres</li>
<li><strong>Calculer les scores</strong> : Comparer les performances de chaque version</li>
<li><strong>Itérer</strong> : Recommencer pour améliorer les résultats</li>
</ol>
<p>Cette approche systématique s&#39;applique à tous les types de modèles : régression, classification, clustering.</p>
<h2>Faire des prédictions</h2>
<p>Une fois le modèle entraîné et évalué, il peut être utilisé pour faire des prédictions sur de nouvelles données. Par exemple, pour estimer le poids d&#39;un nouveau garçon de 150 mois mesurant 153 cm, il suffit de fournir ces valeurs au modèle qui retournera une estimation basée sur les patterns appris.</p>
<h2>En résumé</h2>
<ul>
<li>La <strong>fonction de coût</strong> mesure l&#39;erreur pendant l&#39;entraînement. L&#39;algorithme cherche à la minimiser.</li>
<li>Les <strong>métriques d&#39;évaluation</strong> mesurent la performance finale du modèle sur de nouvelles données.</li>
<li>Pour la régression, attention aux directions :<ul>
<li><strong>R² proche de 1 = bon modèle</strong></li>
<li><strong>RMSE, MAE, MAPE proches de 0 = bon modèle</strong></li>
</ul>
</li>
<li>Le choix des variables prédictives impacte fortement la qualité du modèle.</li>
<li>L&#39;évaluation rigoureuse nécessite de séparer les données en ensembles d&#39;entraînement et de test.</li>
</ul>
<p>La maîtrise de ces concepts d&#39;évaluation est essentielle pour développer des modèles de Machine Learning fiables et performants. Dans les prochains articles, nous explorerons plus en détail les différents types de modèles et leurs spécificités.</p>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Thu, 11 Dec 2025 16:11:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
    <item>
      <title><![CDATA[Les Formules de l'IA : Comprendre le Langage des Prédictions]]></title>
      <link>https://clement-reboul.fr/blog/les-formules-de-l-ia-comprendre-le-langage-des-predictions/</link>
      <guid isPermaLink="true">https://clement-reboul.fr/blog/les-formules-de-l-ia-comprendre-le-langage-des-predictions/</guid>
      <description><![CDATA[Quand on parle d'intelligence artificielle, on imagine souvent des algorithmes complexes et mystérieux. Pourtant, derrière chaque prédiction se cachent des formules mathématiques simples qui orchestrent tout le processus. Décryptons ensemble ces équations qui permettent aux machines d'apprendre et de prédire.]]></description>
      <content:encoded><![CDATA[<p>Quand on parle d&#39;intelligence artificielle, on imagine souvent des algorithmes complexes et mystérieux. Pourtant, derrière chaque prédiction se cachent des formules mathématiques simples qui orchestrent tout le processus. Décryptons ensemble ces équations qui permettent aux machines d&#39;apprendre et de prédire.</p>
<h2>La Régression Linéaire : Le Plan de Construction</h2>
<p><strong>Formule :</strong> <code>y ∼ x₁ + x₂ + ⋯ + xₙ</code></p>
<p>Imaginez que vous voulez prédire le prix d&#39;une maison. Vous avez plusieurs facteurs : la surface (x₁), le nombre de chambres (x₂), la distance au centre-ville (x₃), etc. La régression linéaire, c&#39;est le <strong>plan de construction</strong> de votre modèle.</p>
<p><strong>Ce qu&#39;elle fait :</strong></p>
<ul>
<li>Combine tous vos facteurs d&#39;entrée (les x) pour prédire une valeur continue (y)</li>
<li>Attribue un poids à chaque facteur selon son importance</li>
<li>Trouve la meilleure &quot;ligne&quot; qui relie vos données</li>
</ul>
<p><strong>Logique à retenir :</strong> C&#39;est comme une recette de cuisine. Chaque ingrédient (x) contribue au résultat final (y), et la formule vous dit dans quelles proportions les mélanger.</p>
<p><strong>Exemple concret :</strong></p>
<pre><code>Prix maison ∼ (surface × 2000€) + (chambres × 10000€) - (distance × 500€)
</code></pre>
<h2>RMSE : Le Juge de l&#39;Erreur</h2>
<p><strong>Formule :</strong> <code>RMSE = √(1/N × Σ(yₖ - ŷₖ)²)</code></p>
<p>Une fois votre modèle construit, il faut le juger. Le RMSE (Root Mean Square Error) est le <strong>juge impartial</strong> qui évalue la qualité de vos prédictions pour les valeurs continues.</p>
<p><strong>Ce qu&#39;elle fait :</strong></p>
<ul>
<li>Compare vos prédictions (ŷ) avec les vraies valeurs (y)</li>
<li>Calcule l&#39;écart au carré pour chaque prédiction</li>
<li>Fait la moyenne et prend la racine carrée</li>
</ul>
<p><strong>Logique à retenir :</strong> Plus le chiffre est petit, mieux c&#39;est. Un RMSE de 0 signifierait des prédictions parfaites (en pratique impossible).</p>
<p><strong>Pourquoi c&#39;est important :</strong></p>
<ul>
<li>Un RMSE de 5000€ sur des prédictions de prix de maison ? Acceptable.</li>
<li>Un RMSE de 5000€ sur des prédictions de température ? Catastrophique !</li>
</ul>
<p>Le RMSE doit être interprété dans le contexte de votre problème.</p>
<h2>Le Rappel : L&#39;Agent de Sécurité</h2>
<p><strong>Formule :</strong> <code>Rappel = TP / (TP + FN)</code></p>
<p>Le rappel (ou <em>recall</em> en anglais) est votre <strong>agent de sécurité</strong>. Son job ? Ne rien manquer d&#39;important.</p>
<p><strong>Vocabulaire :</strong></p>
<ul>
<li><strong>TP (True Positive)</strong> : Alarmes justifiées qu&#39;on a détectées</li>
<li><strong>FN (False Negative)</strong> : Alarmes qu&#39;on a ratées (danger !)</li>
</ul>
<p><strong>Ce qu&#39;elle mesure :</strong>
Parmi tous les cas positifs réels, combien en avez-vous détectés ?</p>
<p><strong>Logique à retenir :</strong> Minimiser les FN (Faux Négatifs). On ne veut <strong>rien manquer</strong>.</p>
<p><strong>Exemples d&#39;usage :</strong></p>
<ul>
<li><strong>Détection de spam :</strong> Un rappel de 95% = on a attrapé 95% des spams</li>
<li><strong>Diagnostic médical :</strong> Un rappel de 98% = on a détecté 98% des maladies</li>
<li><strong>Fraude bancaire :</strong> Un rappel de 90% = on a bloqué 90% des transactions frauduleuses</li>
</ul>
<p><strong>Le piège :</strong> On peut avoir un rappel de 100% en classant TOUT comme positif... mais on aura plein de fausses alertes ! D&#39;où l&#39;importance de la précision.</p>
<h2>La Précision : Le Contrôleur Qualité</h2>
<p><strong>Formule :</strong> <code>Précision = TP / (TP + FP)</code></p>
<p>La précision est le <strong>contrôleur qualité</strong> de vos alarmes. Elle répond à la question : &quot;Quand mon modèle dit OUI, a-t-il raison ?&quot;</p>
<p><strong>Vocabulaire :</strong></p>
<ul>
<li><strong>TP (True Positive)</strong> : Alarmes justifiées</li>
<li><strong>FP (False Positive)</strong> : Fausses alarmes (danger !)</li>
</ul>
<p><strong>Ce qu&#39;elle mesure :</strong>
Parmi toutes vos alertes, combien sont vraiment justifiées ?</p>
<p><strong>Logique à retenir :</strong> Minimiser les FP (Faux Positifs). On veut que l&#39;alarme soit <strong>fiable</strong>.</p>
<p><strong>Exemples d&#39;usage :</strong></p>
<ul>
<li><strong>Filtre anti-spam :</strong> Précision de 99% = 99% des emails classés spam sont vraiment des spams</li>
<li><strong>Virement bancaire :</strong> Précision de 95% = 95% des virements bloqués sont réellement frauduleux</li>
<li><strong>Reconnaissance faciale :</strong> Précision de 98% = 98% des identifications sont correctes</li>
</ul>
<p><strong>Le piège :</strong> On peut avoir une précision de 100% en ne détectant que les cas ultra-évidents... mais on ratera beaucoup de cas ! D&#39;où l&#39;importance du rappel.</p>
<h2>Le Dilemme Rappel vs Précision</h2>
<p>En pratique, on doit souvent choisir :</p>
<p><strong>Privilégier le Rappel (ne rien manquer) :</strong></p>
<ul>
<li>Diagnostic médical (mieux vaut une fausse alerte qu&#39;un cancer raté)</li>
<li>Détection de fraude (on accepte de bloquer quelques virements légitimes)</li>
<li>Système de sécurité (mieux vaut une fausse alarme qu&#39;un intrus non détecté)</li>
</ul>
<p><strong>Privilégier la Précision (alarmes fiables) :</strong></p>
<ul>
<li>Recommandations produits (ne pas spammer l&#39;utilisateur)</li>
<li>Validation de documents (ne bloquer que les vrais problèmes)</li>
<li>Notifications push (éviter de fatiguer l&#39;utilisateur avec de fausses alertes)</li>
</ul>
<h2>Conclusion : Les Formules comme Boussole</h2>
<p>Ces formules ne sont pas de simples équations mathématiques. Ce sont des <strong>outils de décision</strong> qui guident la construction et l&#39;évaluation des modèles d&#39;IA :</p>
<ol>
<li><strong>Régression linéaire</strong> : Définit comment combiner les facteurs</li>
<li><strong>RMSE</strong> : Évalue la qualité des prédictions continues</li>
<li><strong>Rappel</strong> : S&#39;assure qu&#39;on ne rate rien d&#39;important</li>
<li><strong>Précision</strong> : S&#39;assure que nos alertes sont fiables</li>
</ol>
<p>Comprendre ces formules, c&#39;est comprendre le langage des prédictions. Et dans un monde où l&#39;IA prend des décisions de plus en plus importantes, savoir décoder ce langage devient essentiel.</p>
<hr>
<p><strong>Pour aller plus loin :</strong></p>
<ul>
<li>F1-Score : La moyenne harmonique entre rappel et précision</li>
<li>AUC-ROC : Pour évaluer globalement un modèle de classification</li>
<li>MAE vs RMSE : Choisir la bonne métrique pour les régressions</li>
</ul>
]]></content:encoded>
      <dc:creator>Clément Reboul</dc:creator>
      <pubDate>Mon, 15 Sep 2025 19:17:00 GMT</pubDate>
      <category>Guides pratiques</category>
    </item>
  </channel>
</rss>
