<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mon Shot de Data Science</title>
    <description>Mes meilleures pratiques en Data Science et Machine Learning (avec Python)</description>
    
    <link>https://www.monshotdata.com/</link>
    <atom:link href="https://rss.beehiiv.com/feeds/cu4gwRrftO.xml" rel="self"/>
    
    <lastBuildDate>Fri, 7 Aug 2026 03:25:53 +0000</lastBuildDate>
    <pubDate>Mon, 03 Aug 2026 09:00:00 +0000</pubDate>
    <atom:published>2026-08-03T09:00:00Z</atom:published>
    <atom:updated>2026-08-07T03:25:53Z</atom:updated>
    
      <category>Data Science</category>
      <category>Machine Learning</category>
      <category>Artificial Intelligence</category>
    <copyright>Copyright 2026, Mon Shot de Data Science</copyright>
    
    <image>
      <url>https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/publication/logo/1f7580ca-bca1-4bd0-ad17-425e1778d89f/MonCoachData-10.png</url>
      <title>Mon Shot de Data Science</title>
      <link>https://www.monshotdata.com/</link>
    </image>
    
    <docs>https://www.rssboard.org/rss-specification</docs>
    <generator>beehiiv</generator>
    <language>en-us</language>
    <webMaster>support@beehiiv.com (Beehiiv Support)</webMaster>

      <item>
  <title>La face cachée de la régularisation L2</title>
  <description>🎯 Shot #325 - Comment elle élimine la multicolinéarité et donne son nom à la ridge regression.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/50d5c888-460a-4221-8e90-b762b6e787da/_325-regularisation-L2.png" length="123228" type="image/png"/>
  <link>https://www.monshotdata.com/p/l2-regularization-avantage-cache-multicollinearite</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/l2-regularization-avantage-cache-multicollinearite</guid>
  <pubDate>Mon, 03 Aug 2026 09:00:00 +0000</pubDate>
  <atom:published>2026-08-03T09:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Quasi tous les tutoriels, cours ou articles de blog parlant de la régularisation L2 que j&#39;ai pu voir n&#39;abordent qu&#39;une seule chose : </p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><hr class="content_break"><p class="paragraph" style="text-align:left;">Bien sûr, ces affirmations sont tout à fait correctes, et je ne le nie absolument pas.</p><p class="paragraph" style="text-align:left;">D&#39;ailleurs, on peut le vérifier avec le schéma ci-dessous :</p><div class="image"><img alt="Comparaison des frontières de décision selon la valeur du paramètre de régularisation λ sur 5 datasets" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/751613b7-b069-4202-b23c-b67a6435736b/_325-regularisation-l2-frontieres-decision-lambda.png.png?t=1785711006"/></div><p class="paragraph" style="text-align:left;">Sur l&#39;image ci-dessus, plus on se déplace vers la droite, plus le paramètre de régularisation augmente, et le modèle crée une frontière de décision plus simple sur les 5 datasets.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Revenons à notre sujet…</p><p class="paragraph" style="text-align:left;">Ce qui me déçoit le plus, c&#39;est que la plupart des ressources ne mentionnent pas que <b>la régularisation L2 est un excellent remède contre la multicolinéarité</b>.</p><p class="paragraph" style="text-align:left;">La multicolinéarité apparaît quand deux (ou plusieurs) features sont fortement corrélées, OU quand deux (ou plusieurs) features permettent de prédire une autre feature :</p><div class="image"><img alt="Illustration de la multicolinéarité entre featureA, featureB et featureC" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/dc9e0ac9-ca77-454f-af5c-06116640538e/_325-multicollinearite-featurea-featureb-featurec.png.png?t=1785711093"/></div><p class="paragraph" style="text-align:left;">Quand on utilise la régularisation L2 dans une régression linéaire, l&#39;algorithme est aussi appelé <b>Ridge regression</b>. </p><div class="image"><img alt="Formule de la ridge regression : somme des carrés des résidus plus la pénalité L2" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3a075f87-19a2-46c4-b268-39daa6191e21/_325-formule-ridge-regression.png.png?t=1785711211"/></div><p class="paragraph" style="text-align:left;">Mais comment la régularisation L2 élimine-t-elle la multicolinéarité ?</p><p class="paragraph" style="text-align:left;">Aujourd&#39;hui, je vais te donner une intuition démonstrative sur ce sujet, qui expliquera aussi <b>pourquoi la &quot;ridge regression&quot; porte ce nom</b>.</p><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="dataset-factice">Dataset factice</h2><p class="paragraph" style="text-align:left;">Pour la démonstration, prenons ce dataset factice à deux features :</p><div class="image"><img alt="Capture de code montrant la création d&#39;un dataset factice avec featureB fortement corrélée à featureA" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e38ec8eb-905a-428a-b698-4a6cbf1cb177/_325-code-dataset-factice-featurea-featureb.png.png?t=1785711263"/></div><p class="paragraph" style="text-align:left;">Comme montré ci-dessus, on a volontairement rendu featureB fortement corrélée à featureA. Cela nous donne un dataset factice avec lequel travailler.</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="rgression-linaire-sans-pnalit-l-2">Régression linéaire sans pénalité L2</h2><p class="paragraph" style="text-align:left;">Lors de la modélisation par régression, l&#39;objectif est de déterminer les paramètres spécifiques <code>(θ₁, θ₂)</code> qui minimisent la somme des carrés des résidus (<code>RSS</code>) :</p><div class="image"><img alt="Formule de la somme des carrés des résidus (RSS) à minimiser" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f94e1e68-fcea-43f9-99f0-d2c7f7692c82/_325-formule-rss-sans-l2.png.png?t=1785711305"/></div><p class="paragraph" style="text-align:left;">Voici ce qu&#39;on va faire :</p><p class="paragraph" style="text-align:left;">On va tracer la valeur du RSS pour de nombreuses combinaisons différentes de paramètres <code>(θ₁, θ₂)</code>. Cela va créer un graphique 3D :</p><ul><li><p class="paragraph" style="text-align:left;">axe x → <code>θ₁</code></p></li><li><p class="paragraph" style="text-align:left;">axe y → <code>θ₂</code></p></li><li><p class="paragraph" style="text-align:left;">axe z → valeur du <code>RSS</code></p></li></ul><p class="paragraph" style="text-align:left;">Ensuite, on va examiner visuellement ce graphique pour repérer les paramètres spécifiques <code>(θ₁, θ₂)</code> qui minimisent la valeur du <code>RSS</code>.</p><p class="paragraph" style="text-align:left;">Allons-y.</p><p class="paragraph" style="text-align:left;">Sans la pénalité L2, on obtient le graphique suivant (<i>c&#39;est le même graphique, mais vu sous différents angles</i>) :</p><div class="image"><img alt="Graphique 3D du RSS sans régularisation L2, montrant une vallée" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f6d28534-f1bc-4a83-b1c2-ed1e9d4e2a50/_325-graphique-rss-vallee-sans-l2.png.png?t=1785711382"/></div><p class="paragraph" style="text-align:left;">Tu as remarqué quelque chose ?</p><p class="paragraph" style="text-align:left;">Le graphique 3D présente une vallée. Il existe plusieurs combinaisons de valeurs de paramètres <code>(θ₁, θ₂)</code> pour lesquelles le <code>RSS</code> est minimal.</p><p class="paragraph" style="text-align:left;"><b>Il est donc impossible d&#39;obtenir une valeur unique pour les paramètres </b><code>(θ₁, θ₂)</code><b> qui minimisent le </b><code>RSS</code><b>.</b></p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="rgression-linaire-avec-pnalit-l-2">Régression linéaire avec pénalité L2</h2><p class="paragraph" style="text-align:left;">Quand on utilise une pénalité L2, l&#39;objectif est de minimiser l&#39;expression suivante :</p><div class="image"><img alt="Formule de la somme des carrés des résidus additionnée de la pénalité L2" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a8b43b42-34d2-4afb-8651-3370b43c9559/_325-formule-rss-avec-l2.png.png?t=1785711433"/></div><p class="paragraph" style="text-align:left;">En traçant à nouveau le même graphique que précédemment, on obtient ceci :</p><div class="image"><img alt="Graphique 3D du RSS avec régularisation L2, sans vallée" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3aa31ec6-d5fb-404e-9ff6-afb384d7aec9/_325-graphique-rss-sans-vallee-avec-l2.png.png?t=1785711482"/></div><p class="paragraph" style="text-align:left;">Tu remarques quelque chose de différent cette fois-ci ?</p><p class="paragraph" style="text-align:left;">Comme le montre l&#39;image ci-dessus, l&#39;utilisation de la régularisation L2 supprime la vallée qu&#39;on avait observée plus tôt et donne un minimum global à l&#39;erreur RSS.</p><p class="paragraph" style="text-align:left;"><b>Il est désormais possible d&#39;obtenir une valeur unique pour les paramètres </b><code>(θ₁, θ₂)</code><b> qui minimise le </b><code>RSS</code><b>.</b></p><p class="paragraph" style="text-align:left;">Comme par magie, la régularisation L2 nous a permis d&#39;éliminer la multicolinéarité.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="pourquoi-le-nom-ridge-regression">Pourquoi le nom &quot;ridge regression&quot; ?</h2><p class="paragraph" style="text-align:left;">C&#39;est d&#39;ailleurs de là que vient le nom &quot;ridge regression&quot; : elle élimine la crête (&quot;ridge&quot;) présente dans la <b>fonction de vraisemblance</b> quand on applique la pénalité L2.</p><div class="image"><img alt="Comparaison visuelle entre une vallée et une crête en montagne" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/12c4d2a2-1517-4799-b37f-a876bb3518f1/_325-comparaison-vallee-crete-montagne.png.png?t=1785711522"/></div><p class="paragraph" style="text-align:left;">Bien sûr, dans les démonstrations qu&#39;on vient de voir, on a observé une vallée, pas une crête.</p><p class="paragraph" style="text-align:left;">Cependant, dans ce cas, on considérait la somme des carrés des résidus, une grandeur qu&#39;on minimise pour obtenir les paramètres optimaux.</p><p class="paragraph" style="text-align:left;">La fonction d&#39;erreur donne donc logiquement une vallée.</p><p class="paragraph" style="text-align:left;">Si on utilisait plutôt la vraisemblance, une grandeur qu&#39;on cherche à maximiser, cela inverserait (en quelque sorte) le graphique et donnerait une crête à la place :</p><div class="image"><img alt="Transformation du graphique RSS (vallée) en fonction de vraisemblance (crête)" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/66aebc68-60a5-4092-ac1a-bad16c15ae88/_325-conversion-vallee-crete-vraisemblance.png.png?t=1785711559"/></div><p class="paragraph" style="text-align:left;">Apparemment, c&#39;est la fonction de vraisemblance qui a été prise en compte au moment de nommer l&#39;algorithme.</p><p class="paragraph" style="text-align:left;">Et c&#39;est pour ça qu&#39;on l&#39;a appelé &quot;ridge regression&quot;.</p><p class="paragraph" style="text-align:left;">Plutôt cool, non ?</p><p class="paragraph" style="text-align:left;">Quand j&#39;ai découvert ça il y a quelques années, je n&#39;avais littéralement aucune idée qu&#39;on avait réfléchi aussi profondément avant de nommer la ridge regression.</p><p class="paragraph" style="text-align:left;">J&#39;espère que tu as appris quelque chose de nouveau aujourd&#39;hui :)</p><p class="paragraph" style="text-align:left;">Si tu veux en savoir plus sur l&#39;origine probabiliste de la régularisation L2, jette un œil à cet article : </p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/regularisation-probabilites?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=la-face-cachee-de-la-regularisation-l2" target="_blank"><div class="embed__content"><p class="embed__title"> Découvrir la Régularisation par les Probabilités </p><p class="embed__description"> Découvre comment éviter le surapprentissage en machine learning grâce à la régularisation par probabilités et techniques MLE pour des modèles performants et généralisables. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/6e2c3741-5f38-4ecf-9407-4ffe5e5eb0b8/Mini-cours__6_-_De%CC%81couvrir_la_Re%CC%81gularisation_par_les_Probabilite%CC%81s.png?t=1772986383"/></a></div><hr class="content_break"><p class="paragraph" style="text-align:left;">👉 À toi de jouer : quels sont, selon toi, d&#39;autres avantages de la régularisation L2 ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=c551a9a3-7dff-4e42-840e-ce37c2d0c540&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Python ne respecte pas vraiment l&#39;encapsulation en POO</title>
  <description>🎯 Shot #324 - Ce que tout développeur Python doit absolument savoir sur public, protégé et privé.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/464a23f3-d16b-4f62-af34-e3dacef672c8/_324-python-encapsulation-convention-developpeur.png.png" length="200879" type="image/png"/>
  <link>https://www.monshotdata.com/p/python-encapsulation-poo</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/python-encapsulation-poo</guid>
  <pubDate>Tue, 28 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-28T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Python]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Utiliser des modificateurs d&#39;accès (public, protégé et privé) est fondamental pour l&#39;encapsulation en POO.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/942fd984-6cf7-4bbd-afd3-8482bd0d1c52/_324-python-encapsulation-public-protege-prive.png.png?t=1785228562"/></div><p class="paragraph" style="text-align:left;">Ce n&#39;est pas propre à Python, c&#39;est valable pour la POO en général.</p><p class="paragraph" style="text-align:left;">Mais quand on parle spécifiquement de Python, on remarque qu&#39;il ne propose pas de véritables mécanismes d&#39;encapsulation, ceux-là mêmes qu&#39;on voudrait pourtant exploiter dans son code orienté objet.</p><p class="paragraph" style="text-align:left;">Comment ça ?</p><p class="paragraph" style="text-align:left;">Voyons ça ensemble aujourd&#39;hui !</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Comme tu le sais peut-être déjà, les attributs de classe en POO peuvent être de trois types :</p><ul><li><p class="paragraph" style="text-align:left;">Un <b>membre public</b> est accessible partout, à l&#39;intérieur comme à l&#39;extérieur de la classe de base, et il est hérité par toutes les classes enfants.</p></li><li><p class="paragraph" style="text-align:left;">Un <b>membre protégé</b> est accessible partout dans la classe de base et ses classe(s) enfant(s). Il n&#39;est pas accessible en dehors de la classe.</p></li><li><p class="paragraph" style="text-align:left;">Un <b>membre privé</b> n&#39;est accessible qu&#39;à l&#39;intérieur de la classe de base.</p></li></ul><p class="paragraph" style="text-align:left;">Mais avec Python, il n&#39;existe aucune contrainte stricte de ce type. C&#39;est différent de nombreux autres langages, comme le C++.</p><p class="paragraph" style="text-align:left;">Ainsi, les membres protégés se comportent exactement comme des membres publics.</p><p class="paragraph" style="text-align:left;">Et ce n&#39;est pas tout, les membres privés peuvent eux aussi (d&#39;une certaine manière) être accédés depuis l&#39;extérieur de la classe.</p><p class="paragraph" style="text-align:left;">Pour mieux comprendre, regarde l&#39;implémentation de classe suivante :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8e6559ab-d288-4e05-b734-cafe36b5c0f4/_324-python-encapsulation-code-declarat.png.png?t=1785228596"/></div><p class="paragraph" style="text-align:left;">D&#39;un point de vue syntaxique, en Python :</p><ul><li><p class="paragraph" style="text-align:left;">Un <b>membre public</b> se déclare <b>sans underscore</b> au début.</p></li><li><p class="paragraph" style="text-align:left;">Un <b>membre protégé</b> se déclare avec <b>1 underscore</b> au début.</p></li><li><p class="paragraph" style="text-align:left;">Un <b>membre privé</b> se déclare avec <b>2 underscores</b> au début.</p></li></ul><p class="paragraph" style="text-align:left;">Ensuite, on instancie un objet de la classe :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d8e1d877-48e8-473c-8f6e-1882b2bf768d/_324-python-encapsulation-instanciation-objet.png.png?t=1785228621"/></div><p class="paragraph" style="text-align:left;">Comme on peut s&#39;y attendre, l&#39;attribut public est accessible depuis l&#39;extérieur de la classe :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3f5f9b02-70e5-4bc2-9042-905cae8c1079/_324-python-encapsulation-attribut-public-accessible.png.png?t=1785228644"/></div><p class="paragraph" style="text-align:left;">Cependant, de la même façon, même l&#39;attribut protégé est accessible depuis l&#39;extérieur de la classe, ce qui, en théorie, ne devrait pas arriver :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/36d4f456-5da6-421a-a4fe-ebc6f70b320d/_324-python-encapsulation-attribut-protege-accessible.png.png?t=1785228679"/></div><p class="paragraph" style="text-align:left;">Enfin, quand on déclare des membres privés, Python effectue ce qu&#39;on appelle le <i>name mangling</i>.</p><p class="paragraph" style="text-align:left;">C&#39;est une technique utilisée en programmation pour éviter les conflits de noms entre différentes classes.</p><p class="paragraph" style="text-align:left;">Python réalise ce name mangling en ajoutant le nom de la classe précédé d&#39;un underscore (<code>_MyClass</code>) devant tous les membres qui commencent par deux underscores.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9856b1c4-08bb-46d3-b89f-1a9a594e4a5f/_324-python-encapsulation-name-mangling-schema.png.png?t=1785228702"/></div><p class="paragraph" style="text-align:left;">Ainsi, même si le membre privé n&#39;est pas directement accessible avec son nom d&#39;origine, il reste accessible avec le nom modifié obtenu grâce au name mangling.</p><p class="paragraph" style="text-align:left;">C&#39;est ce que montre l&#39;exemple suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4d4643a6-e010-4f56-9250-cc0d5296d3f0/_324-python-encapsulation-name-mangling-exemple.png.png?t=1785228723"/></div><p class="paragraph" style="text-align:left;">Comme le montrent tous les exemples ci-dessus, les membres protégés et les membres privés (grâce au name mangling) peuvent être accédés comme des membres publics.</p><p class="paragraph" style="text-align:left;">Le point essentiel à retenir pour tout développeur Python qui utilise la POO, c&#39;est que Python n&#39;impose jamais l&#39;encapsulation.</p><p class="paragraph" style="text-align:left;"><b>En réalité, exploiter les mécanismes d&#39;encapsulation en Python repose surtout sur des conventions.</b></p><p class="paragraph" style="text-align:left;">Elles servent à communiquer aux autres développeurs les règles d&#39;accessibilité des membres d&#39;une classe.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/464a23f3-d16b-4f62-af34-e3dacef672c8/_324-python-encapsulation-convention-developpeur.png.png?t=1785228742"/></div><p class="paragraph" style="text-align:left;">C&#39;est donc à chaque développeur de respecter ces conventions.</p><p class="paragraph" style="text-align:left;">Voici un guide complet sur la POO en Python si tu veux approfondir le sujet : </p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/poo-python-data-scientists-partie1?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=python-ne-respecte-pas-vraiment-l-encapsulation-en-poo" target="_blank"><div class="embed__content"><p class="embed__title"> Programmation orientée objet avec Python pour les data scientists (Partie 1) </p><p class="embed__description"> Apprends la programmation orientée objet en Python : classes, objets, méthodes magiques et héritage, appliqués aux pipelines data pour data scientists. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/6d251a3f-b8eb-4ac5-98f5-8a30850be514/Mini-cours__15_-_Programmation_oriente%CC%81e_objet_avec_Python_pour_les_data_scientists.png?t=1772986035"/></a></div><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/poo-python-data-scientists-partie2?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=python-ne-respecte-pas-vraiment-l-encapsulation-en-poo" target="_blank"><img class="embed__image embed__image--left" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/ea3c7186-f04b-4433-b550-86ff28efc9d8/Mini-cours__16_-_Code10.png?t=1772986036"/><div class="embed__content"><p class="embed__title"> Programmation orientée objet avec Python pour les data scientists (Partie 2) </p><p class="embed__description"> Approfondis la POO en Python : polymorphisme, encapsulation, classes avancées et optimisation pour des modèles de machine learning robustes. </p></div></a></div><p class="paragraph" style="text-align:left;">👉 <b>À toi de jouer :</b> quels sont les autres points de vigilance à connaître dans la POO en Python ?</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Prêt à passer au niveau supérieur ?</p></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=64c1a82c-6b78-4da5-bc46-44378ecd267a&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Maîtriser l&#39;entraînement multi-GPU : DataParallel, DDP et learning rate</title>
  <description>👀​ Mini-cours #36 - La mécanique complète derrière la distribution de l&#39;entraînement sur plusieurs GPU, pour scaler tes modèles sans mauvaises surprises.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5acc2555-842c-4ac6-801b-8eedb13b4a1f/Mini-cours_36-Entrainement-multi-GPU.png" length="67571" type="image/png"/>
  <link>https://www.monshotdata.com/p/entrainement-multi-gpu-pytorch-dataparallel-ddp</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/entrainement-multi-gpu-pytorch-dataparallel-ddp</guid>
  <pubDate>Wed, 22 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-22T10:00:00Z</atom:published>
    <category><![CDATA[Deep Learning]]></category>
    <category><![CDATA[Scaling &amp; Calcul Distribué]]></category>
    <category><![CDATA[Pro]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#f2eafe;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:left;"><span style="text-decoration:underline;"><b>Psst... Contenu Exclusif Réservé aux Membres !</b></span><br><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Ce mini-cours fait partie de notre espace premium. Rejoins dès maintenant le </span><b>Cercle des Experts</b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;"> pour débloquer l’intégralité de nos ressources, analyses approfondies et guides pratiques.</span><br><b>👉 </b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Clique ici pour découvrir les avantages et t’inscrire : </span><b><a class="link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=maitriser-l-entrainement-multi-gpu-dataparallel-ddp-et-learning-rate" target="_blank" rel="noopener noreferrer nofollow" style="color: #2563eb">Page d’adhésion</a></b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">.</span></p></div><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#222222;font-family:Poppins, Helvetica, sans-serif, serif, EmojiFont;font-size:16px;">⏱️ </span><i><b>Temps de lecture</b></i><i> : environ 35 minutes</i></p></div><p class="paragraph" style="text-align:left;">Dans le dossier consacré à PyTorch Lightning, on n&#39;avait pas abordé l&#39;entraînement multi-GPU. </p><p class="paragraph" style="text-align:left;">Je t&#39;avais prévenu que le sujet demandait des bases supplémentaires : comment ça fonctionne sous le capot, quelles stratégies existent, comment plusieurs GPU restent synchronisés entre eux pendant l&#39;entraînement en environnement distribué, les points de vigilance à avoir, et bien plus encore.</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/pytorch-lightning-guide-complet?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=maitriser-l-entrainement-multi-gpu-dataparallel-ddp-et-learning-rate" target="_blank"><div class="embed__content"><p class="embed__title"> PyTorch Lightning : guide complet pour débuter </p><p class="embed__description"> Apprends à utiliser PyTorch Lightning pour simplifier l&#39;entraînement de tes modèles deep learning : callbacks, métriques, précision mixte et profiling. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/571757f7-f067-4ce1-a5bc-899051c54603/Mini-cours__30_-_PyTorch_Lightning___PyTorch_booste%CC%81.png?t=1778253798"/></a></div><p class="paragraph" style="text-align:left;">Aujourd&#39;hui, on reprend ce fil. Direction les rouages techniques de l&#39;entraînement multi-GPU : comment ça marche en interne, et les détails propres à l&#39;implémentation.</p><p class="paragraph" style="text-align:left;">On va aussi passer en revue les points de vigilance essentiels pour l&#39;entraînement multi-GPU (ou distribué). Mal gérés, ils peuvent entraîner des performances sous-optimales, un entraînement plus lent, voire une instabilité pendant l&#39;entraînement.</p><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="pourquoi-passer-au-multi-gpu">Pourquoi passer au multi-GPU</h2><p class="paragraph" style="text-align:left;">Par défaut, les modèles de deep learning construits avec PyTorch ne s&#39;entraînent que sur un seul GPU, même si plusieurs GPU sont disponibles.</p><div class="image"><img alt="Schéma montrant PyTorch qui n&#39;utilise qu&#39;un seul GPU actif, les GPU environnants restant inactifs" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/79ebae4c-a3cb-45fd-8a90-15917eebab0a/Mini-cours_36-multi-gpu-01-un-seul-gpu-actif.png.png?t=1784620109"/></div><p class="paragraph" style="text-align:left;">Cela ne veut pas dire qu&#39;on ne peut pas faire de l&#39;entraînement multi-GPU avec PyTorch, bien au contraire. Mais ça demande de mobiliser explicitement les capacités de traitement parallèle de PyTorch.</p><p class="paragraph" style="text-align:left;">De plus, même en exploitant plusieurs GPU avec PyTorch, les procédures d&#39;entraînement classiques restent limitées à une seule machine. Cette limitation vient du comportement par défaut de PyTorch, qui utilise une seule machine pour l&#39;entraînement du modèle.</p><div class="image"><img alt="Schéma illustrant qu&#39;un modèle PyTorch s&#39;entraîne par défaut sur une seule machine" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9e685fb2-0f43-485b-8b40-c26aa79c4e61/Mini-cours_36-multi-gpu-02-pytorch-machine-unique.png.png?t=1784620223"/></div><p class="paragraph" style="text-align:left;">Ça devient donc un goulot d&#39;étranglement sévère dès qu&#39;on travaille avec des datasets volumineux qui demandent plus de puissance de calcul qu&#39;une seule machine ne peut en fournir.</p><p class="paragraph" style="text-align:left;">Mais réaliser qu&#39;on est limité à une seule machine pour l&#39;entraînement, c&#39;est aussi réaliser qu&#39;il reste une marge importante d&#39;optimisation du temps d&#39;exécution.</p><div class="image"><img alt="Schéma illustrant le passage d&#39;un modèle PyTorch à un entraînement distribué sur plusieurs machines" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e3da6001-8cd5-48b6-bb1e-b0c1ae484912/Mini-cours_36-multi-gpu-03-scaler-plusieurs-machines.png.png?t=1784620335"/></div><p class="paragraph" style="text-align:left;">L&#39;entraînement multi-GPU résout ce problème.</p><p class="paragraph" style="text-align:left;">En résumé (et comme son nom l&#39;indique), l&#39;entraînement multi-GPU permet de répartir la charge de travail de l&#39;entraînement sur plusieurs GPU, voire sur plusieurs machines si nécessaire.</p><p class="paragraph" style="text-align:left;">Ça réduit considérablement le temps d&#39;entraînement pour les gros datasets et les modèles complexes, en exploitant la puissance de calcul combinée du matériel disponible.</p><p class="paragraph" style="text-align:left;">Il existe plusieurs façons (stratégies) de faire du multi-GPU, mais l&#39;une des plus courantes consiste à laisser chaque GPU ou chaque machine traiter une portion des données d&#39;entrée de façon <b>indépendante</b>.</p><p class="paragraph" style="text-align:left;">C&#39;est ce qu&#39;on appelle le parallélisme de données (data parallelism).</p><div class="section" style="background-color:#e0f2f9;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:left;">💡 En plus du parallélisme de données, d&#39;autres stratégies comme le parallélisme de modèle (model parallelism), le parallélisme de pipeline (pipeline parallelism) et le parallélisme hybride permettent aussi de faire du multi-GPU. Chacune a ses avantages et ses inconvénients, et le choix dépend des besoins spécifiques du modèle et du matériel disponible. On en reparle brièvement en fin de dossier.</p></div><h2 class="heading" style="text-align:left;" id="le-paralllisme-de-donnes">Le parallélisme de données</h2><p class="paragraph" style="text-align:left;">Dans le parallélisme de données, l&#39;idée consiste à diviser les données disponibles en petits batches, chaque batch étant traité par un GPU distinct.</p><div class="image"><img alt="Schéma du parallélisme de données : le dataset complet est divisé en batches traités par plusieurs GPU puis agrégés en un modèle mis à jour" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d2939064-d85f-40b4-a501-aa5522b45c98/Mini-cours_36-multi-gpu-04-parallelisme-donnees-schema.png.png?t=1784620423"/></div><p class="paragraph" style="text-align:left;">À la fin, les mises à jour de chaque GPU sont agrégées et utilisées pour mettre à jour les paramètres du modèle.</p><p class="paragraph" style="text-align:left;">Si tu te souviens du dossier sur l&#39;apprentissage fédéré (federated learning), l&#39;idée va te sembler familière :</p><div class="image"><img alt="Animation illustrant l&#39;apprentissage fédéré, avec un serveur central échangeant des modèles globaux et mis à jour avec plusieurs devices en entraînement local" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/62e45dea-0cfe-4353-8527-141e0e51c45c/Mini-cours_36-multi-gpu-05-apprentissage-federe.gif?t=1784620498"/></div><p class="paragraph" style="text-align:left;">En apprentissage fédéré, au lieu d&#39;avoir un seul serveur centralisé qui traite toutes les données, le modèle s&#39;entraîne sur plusieurs devices en périphérie décentralisés, chacun avec ses propres données. Les mises à jour de ces devices sont ensuite agrégées pour améliorer le modèle global.</p><p class="paragraph" style="text-align:left;">De la même façon, en parallélisme de données, chaque GPU joue le rôle d&#39;un &quot;mini-serveur&quot; : il traite une portion des données et met à jour les paramètres du modèle localement.</p><p class="paragraph" style="text-align:left;">Ces mises à jour locales sont ensuite combinées pour mettre à jour le modèle global. Ce traitement parallèle des données accélère non seulement l&#39;entraînement, mais permet aussi une utilisation efficace des ressources en environnement distribué.</p><p class="paragraph" style="text-align:left;">Une différence majeure : en apprentissage fédéré, on n&#39;a pas d&#39;accès direct au dataset local, alors qu&#39;en parallélisme de données, les données sont directement accessibles.</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/guide-pratique-apprentissage-federe?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=maitriser-l-entrainement-multi-gpu-dataparallel-ddp-et-learning-rate" target="_blank"><div class="embed__content"><p class="embed__title"> Apprentissage Fédéré : Le Guide pour une IA Privée et Performante </p><p class="embed__description"> Ne centralise plus tes données. Découvre comment implémenter l&#39;apprentissage fédéré pour entraîner des modèles sur des données réelles (non-IID) tout en garantissant la confidentialité. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/fa20e8e5-e2aa-4906-8a6b-8da7bbef4a51/Mini-cours__23_-_Couverture_Apprentissage_Fe%CC%81de%CC%81re%CC%81.png.png?t=1773228544"/></a></div><p class="paragraph" style="text-align:left;">Cela dit, il est assez évident que cette approche améliore non seulement l&#39;efficacité de l&#39;entraînement, mais permet aussi de scaler l&#39;entraînement pour gérer des datasets plus volumineux et des modèles plus complexes que ce qu&#39;un seul GPU ou une seule machine pourrait gérer.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="les-stratgies-de-paralllisme-de-don">Les stratégies de parallélisme de données</h2><p class="paragraph" style="text-align:left;">Comme on vient de le voir, le <b>parallélisme de données</b> est une technique qui consiste à paralléliser l&#39;entraînement d&#39;un modèle en répartissant les données sur plusieurs devices (GPU ou machines), puis en combinant les résultats.</p><p class="paragraph" style="text-align:left;">Assez intuitivement, cette approche réduit considérablement le temps d&#39;entraînement des gros modèles et des gros datasets, en exploitant la puissance de calcul combinée de plusieurs devices.</p><p class="paragraph" style="text-align:left;">Il existe principalement deux approches pour faire du parallélisme de données.</p><h3 class="heading" style="text-align:left;" id="1-data-parallel-dp">#1) DataParallel (DP)</h3><h4 class="heading" style="text-align:left;" id="comment-a-marche">Comment ça marche ?</h4><p class="paragraph" style="text-align:left;">DataParallel implémente le parallélisme de données au niveau du module, sur une seule machine disposant de plusieurs GPU.</p><p class="paragraph" style="text-align:left;">En PyTorch (ou PyTorch Lightning), un &quot;module&quot; désigne l&#39;ensemble du modèle de réseau de neurones.</p><p class="paragraph" style="text-align:left;">Donc quand on parle de &quot;parallélisme de données au niveau du module&quot;, ça veut dire que la parallélisation s&#39;applique à tout le module du réseau de neurones, y compris tous ses paramètres et toutes ses opérations.</p><p class="paragraph" style="text-align:left;">Par exemple, si tu as un modèle de deep learning avec plusieurs couches, le parallélisme de données au niveau du module consiste à répliquer ce modèle entier sur plusieurs GPU.</p><div class="image"><img alt="Schéma montrant la réplication d&#39;un modèle sur plusieurs GPU dans la stratégie DataParallel" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ee61eb3-f2fb-4999-b7cf-d3b210417e47/Mini-cours_36-multi-gpu-06-dataparallel-replication-modele.png.png?t=1784620600"/></div><p class="paragraph" style="text-align:left;">Chaque réplique du modèle traite ensuite une portion des données d&#39;entrée de façon indépendante, et les mises à jour reçues de chaque réplique sont ensuite combinées pour mettre à jour les paramètres du modèle.</p><p class="paragraph" style="text-align:left;">Concrètement, la stratégie DataParallel fonctionne ainsi :</p><ul><li><p class="paragraph" style="text-align:left;">Répliquer le modèle sur tous les GPU.</p></li><li><p class="paragraph" style="text-align:left;">Exécuter le forward pass sur le sous-ensemble de données reçu par chaque GPU, et renvoyer les <b>outputs</b> (pas les gradients) à la machine centrale.</p></li></ul><div class="image"><img alt="Schéma montrant chaque GPU traitant son batch de données et produisant ses outputs dans la stratégie DataParallel" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6b422de4-5840-4797-9e94-00f493429c2c/Mini-cours_36-multi-gpu-07-dataparallel-forward-pass.png.png?t=1784620697"/></div><ul><li><p class="paragraph" style="text-align:left;">Une fois les outputs reçus, la machine centrale calcule les gradients :</p></li></ul><div class="image"><img alt="Schéma montrant la machine centrale recevant les outputs de chaque GPU et calculant les gradients" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2db91860-922d-4254-9df0-27b912e23cb0/Mini-cours_36-multi-gpu-08-dataparallel-calcul-gradients.png.png?t=1784620799"/></div><ul><li><p class="paragraph" style="text-align:left;">Enfin, les gradients sont communiqués en retour à chaque GPU pour mettre à jour les répliques individuelles du modèle :</p></li></ul><div class="image"><img alt="Schéma montrant la machine centrale communiquant les gradients calculés à chaque réplique du modèle" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/911ebb43-afb5-4990-a50d-babdd3a73717/Mini-cours_36-multi-gpu-09-dataparallel-communication-updates.png?t=1784620874"/></div><hr class="content_break"><div class="section" style="background-color:#1B3A6B;border-color:#F7931E;border-radius:8px;border-style:solid;border-width:3px;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;">💡<span style="color:#F9FAFB;"> En continuant, tu vas découvrir : </span></p><ul><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Le code PyTorch Lightning pas à pas pour lancer un entraînement multi-GPU, et pourquoi une partie de ce code ne fonctionne plus sur les versions récentes</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Les limites concrètes de DataParallel qui expliquent sa disparition de Lightning</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Comment DistributedDataParallel synchronise les GPU sans faire exploser la mémoire</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">La règle de mise à l&#39;échelle du learning rate (Linear Scaling Rule) et pourquoi l&#39;ignorer peut instabiliser ton entraînement</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Les autres stratégies de parallélisme (modèle, tenseurs) pour aller plus loin</span></p></li></ul></div><div class="paywall"><hr class="paywall__break"/><div class="paywall__content"><h2 class="paywall__header"> La suite de ce mini-cours est réservée aux membres du Cercle des Experts. </h2><p class="paywall__description"> Tu as déjà le début. Pour accéder à l’explication complète et à tous les contenus avancés, rejoins le Cercle des Experts dès maintenant. </p><p class="paywall__links"><a class="paywall__upgrade_link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=maitriser-l-entrainement-multi-gpu-dataparallel-ddp-et-learning-rate">Rejoindre le Cercle des Experts</a> Translation missing: en.app.shared.conjuction.or <a class="paywall__login_link" href="https://www.monshotdata.com/login?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=maitriser-l-entrainement-multi-gpu-dataparallel-ddp-et-learning-rate">Sign In</a></p><div class="paywall__upsell"><div class="paywall__upsell_header"><h3> En devenant membre, tu débloques </h3></div><ul class="paywall__upsell_features"><li class="paywall__upsell_feature"> L’intégralité de ce mini-cours (sans coupure) </li><li class="paywall__upsell_feature"> Tous les mini-cours archivés et les ressources associées </li><li class="paywall__upsell_feature"> 1 nouveau mini-cours chaque semaine pour progresser en continu </li></ul></div></div></div></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a84ddd74-6870-4dae-a6aa-a645dffc3e3e&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>L&#39;étape que la plupart des Data Scientists sautent après la cross-validation</title>
  <description>🎯 Shot #323 - Réentraîner sur toutes les données ou garder le meilleur modèle ? Voici comment trancher.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/74060c69-65ea-4e25-8220-f5b50b6c257d/_323-cover-merge-retrain-full-data.png" length="65548" type="image/png"/>
  <link>https://www.monshotdata.com/p/finaliser-modele-apres-cross-validation</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/finaliser-modele-apres-cross-validation</guid>
  <pubDate>Fri, 17 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-17T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Aujourd&#39;hui, je vais te poser une question.</p><p class="paragraph" style="text-align:left;">Mais avant ça, imagine que tu es en train de construire un modèle de machine learning supervisé.</p><p class="paragraph" style="text-align:left;">Tu utilises la cross-validation pour déterminer un ensemble optimal d&#39;hyperparamètres.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="un-peu-de-contexte"><b>Un peu de contexte : </b></h2><p id="un-peu-de-contexte-la-crossvalidati" class="paragraph" style="text-align:left;">La cross-validation consiste à partitionner <b>plusieurs fois</b> les données disponibles en sous-ensembles, à entraîner le modèle sur certains d&#39;entre eux, puis à le valider sur les sous-ensembles restants.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0b04bea2-275b-491d-aafb-a98fb2cf16ed/_323-cv-folds-train-validation-split.png.png?t=1784124803"/></div><p class="paragraph" style="text-align:left;">Le principal avantage de la cross-validation, c&#39;est qu&#39;elle fournit une estimation plus robuste et moins biaisée de la performance du modèle, comparée à la méthode de validation traditionnelle.</p><p class="paragraph" style="text-align:left;">Autrement dit, ajuster des modèles de machine learning sur un seul validation set peut être trompeur et donner parfois des résultats trop optimistes.</p><p class="paragraph" style="text-align:left;">Cela peut arriver à cause d&#39;un découpage aléatoire des données un peu trop chanceux, ce qui donne un modèle qui performe exceptionnellement bien sur le validation set, mais mal sur des données nouvelles et jamais vues.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/68a6d953-13dc-4513-9ead-7908652b0e7d/_323-validation-set-vs-test-set.png.png?t=1784124845"/></div><p class="paragraph" style="text-align:left;">Voici un post complet sur la cross-validation si tu veux creuser le sujet : <a class="link" href="https://www.monshotdata.com/p/validation-croisee?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=l-etape-que-la-plupart-des-data-scientists-sautent-apres-la-cross-validation" target="_blank" rel="noopener noreferrer nofollow">5 techniques de cross-validation à connaître, expliquées en images</a>.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Pour revenir à notre sujet...</p><p class="paragraph" style="text-align:left;">En résumé, chaque configuration d&#39;hyperparamètres correspond à une performance de cross-validation :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a3fd627f-50a1-45d9-8807-c4e5d9de62c6/_323-hyperparameters-cv-performance.png.png?t=1784124913"/></div><p class="paragraph" style="text-align:left;">Une fois qu&#39;on a obtenu les meilleurs hyperparamètres, il faut finaliser un modèle (disons pour la production), sinon à quoi bon tout ce travail ?</p><p class="paragraph" style="text-align:left;">Voici donc la question : </p><p class="paragraph" style="text-align:left;">Une fois les hyperparamètres optimaux obtenus, que serais-tu le plus enclin à faire ?</p><ol start="1"><li><p class="paragraph" style="text-align:left;">Réentraîner le modèle sur l&#39;intégralité des données (train + validation + test) avec les hyperparamètres optimaux ?</p></li></ol><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cdbe3a00-3940-4971-9635-1f6309ddefcd/_323-merge-retrain-full-data.png.png?t=1784124945"/></div><p class="paragraph" style="text-align:left;">Si on fait ça, il faut garder en tête qu&#39;on ne peut plus valider ce nouveau modèle de façon fiable, puisqu&#39;il ne reste plus de données jamais vues.</p><ol start="2"><li><p class="paragraph" style="text-align:left;">Simplement garder le modèle le plus performant selon la performance de cross-validation elle-même. </p></li></ol><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8388aa84-8fe7-41df-8fa4-e11e4f981b64/_323-hyperparameters-cv-performance-selected.png.png?t=1784124975"/></div><p class="paragraph" style="text-align:left;">Si on fait ça, il faut garder en tête qu&#39;on laisse de côté des données importantes, avec lesquelles on aurait pu entraîner notre modèle.</p><p class="paragraph" style="text-align:left;">Toi, tu ferais quoi ?</p><p class="paragraph" style="text-align:left;">Note ta réponse ci-dessous avant de lire la réponse (le sondage est anonyme) : </p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="ma-recommandation">Ma recommandation</h2><p class="paragraph" style="text-align:left;">Ma préférence a presque toujours été de réentraîner un nouveau modèle avec toutes les données.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cdbe3a00-3940-4971-9635-1f6309ddefcd/_323-merge-retrain-full-data.png.png?t=1784124945"/></div><p class="paragraph" style="text-align:left;">Il y a bien sûr certaines choses à garder en tête, que j&#39;ai appris au fil des modèles que j&#39;ai construits et déployés.</p><p class="paragraph" style="text-align:left;">Cela dit, dans la plupart des cas, réentraîner reste la meilleure façon de procéder.</p><p class="paragraph" style="text-align:left;">Laisse-moi t&#39;expliquer.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="pourquoi-rentraner-le-modle">Pourquoi réentraîner le modèle ?</h2><p class="paragraph" style="text-align:left;">On a envie de réentraîner un nouveau modèle parce que, d&#39;une certaine manière, on est déjà satisfait de la performance de cross-validation, qui, par nature, est une métrique out-of-fold.</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><p class="paragraph" style="text-align:left;">Autrement dit, on croit déjà que le modèle se comportera comme prévu sur des données jamais vues.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8572a060-1275-4c5b-a296-481ca7daada8/_323-cv-performance-good-93-5.png.png?t=1784125049"/></div><p class="paragraph" style="text-align:left;">Ainsi, intégrer ce validation set jamais vu dans les données d&#39;entraînement et réentraîner le modèle n&#39;aura TRÈS PROBABLEMENT AUCUN effet sur sa performance sur des données jamais vues après le déploiement (en supposant qu&#39;aucun covariate shift soudain ne soit entré en jeu, ce qui est un tout autre sujet).</p><p class="paragraph" style="text-align:left;">Si, en revanche, on n&#39;était pas satisfait de la performance de cross-validation elle-même, on ne penserait même pas à finaliser un modèle en premier lieu.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f6fb1d03-98fa-41bc-8201-7c748ce1da23/_323-cv-performance-bad-53-5.png.png?t=1784125084"/></div><p class="paragraph" style="text-align:left;">À la place, on chercherait plutôt des façons d&#39;améliorer le modèle en travaillant sur le feature engineering, en testant de nouveaux hyperparamètres, en expérimentant avec différents modèles, etc.</p><p class="paragraph" style="text-align:left;">Ce raisonnement a aussi du sens intuitivement.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">J&#39;ai du mal à me souvenir d&#39;un cas où réentraîner a eu un effet catastrophique sur le modèle global.</p><p class="paragraph" style="text-align:left;">En fait, je me souviens très bien d&#39;une fois où, pendant que je mettais le modèle en production (ça m&#39;a pris quelques jours après le réentraînement), l&#39;équipe avait rassemblé un peu plus de données labellisées.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6592be46-75e4-4d62-a3ed-6f19f5ca2fda/_323-model-productionizing-pipeline.png.png?t=1784125118"/></div><p class="paragraph" style="text-align:left;">Le modèle n&#39;a montré aucune dégradation de performance quand je l&#39;ai évalué (histoire de vérifier, juste au cas où).</p><p class="paragraph" style="text-align:left;">Comme bénéfice supplémentaire, ça m&#39;a aussi permis de m&#39;assurer que je n&#39;avais fait aucune erreur en mettant mon modèle en production.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="quelques-points-garder-en-tte">Quelques points à garder en tête</h2><p class="paragraph" style="text-align:left;"><b>Attention, ce n&#39;est pas une règle absolue : il ne faut pas toujours réentraîner un nouveau modèle.</b></p><p class="paragraph" style="text-align:left;">Le domaine lui-même, et les problèmes qu&#39;on peut résoudre, sont très divers. Il faut donc rester ouvert d&#39;esprit face au problème qu&#39;on a sous les yeux.</p><p class="paragraph" style="text-align:left;">Une des raisons pour lesquelles je ne voudrais pas réentraîner un nouveau modèle, c&#39;est que ça prend des jours, voire des semaines, pour entraîner le modèle.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ebb49210-5fbf-4fe8-960b-a93d2a44abd4/_323-retrain-full-data-time-concern.png.png?t=1784125145"/></div><p class="paragraph" style="text-align:left;">En fait, même si on réentraîne un nouveau modèle, il existe DE NOMBREUSES situations business où les enjeux sont tout simplement trop élevés.</p><p class="paragraph" style="text-align:left;">On ne peut donc jamais se permettre d&#39;être négligent et de déployer un modèle sans le réévaluer, la fraude transactionnelle, par exemple.</p><p class="paragraph" style="text-align:left;">Dans ce genre de cas, j&#39;ai vu des équipes travailler sur la mise en production du modèle, pendant que les data engineers rassemblaient un peu plus de données en parallèle.</p><p class="paragraph" style="text-align:left;">Avant de déployer, l&#39;équipe faisait quelques vérifications finales sur ce dataset.</p><p class="paragraph" style="text-align:left;">Les nouvelles données rassemblées sont ensuite prises en compte dans les itérations suivantes d&#39;amélioration du modèle.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi de jouer :</b> quelles autres considérations ajouterais-tu ici ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=d20f1b5d-575a-4fec-b086-cdcac70a264c&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>__init__() ne crée pas tes objets en Python</title>
  <description>🎯 Shot #322 - La vraie méthode responsable, c&#39;est __new__(). Voici pourquoi.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/193ed94b-1b5b-47b4-9479-0d0e7c06807d/_322_-_Code2.png.png" length="299877" type="image/png"/>
  <link>https://www.monshotdata.com/p/init-vs-new-python</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/init-vs-new-python</guid>
  <pubDate>Mon, 13 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-13T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Python]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">La plupart des programmeurs Python se trompent sur la méthode magique <code>__init__()</code> en programmation orientée objet (POO). Ils pensent qu&#39;elle crée un nouvel objet, c&#39;est-à-dire qu&#39;elle lui alloue de la mémoire.</p><p class="paragraph" style="text-align:left;">Par exemple, prends la classe <code>Point2D</code> ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/eea60949-10d1-415e-9421-88c93be4795a/_322_-_Code1.png.png?t=1783802389"/><div class="image__source"><span class="image__source_text"><p>Suppose qu&#39;il existe aussi une méthode <code>__repr__()</code>, même si elle n&#39;est pas montrée ici.</p></span></div></div><p class="paragraph" style="text-align:left;">Quand on crée un objet (comme ci-dessous), les programmeurs pensent qu&#39;en arrière-plan, c&#39;est la méthode <code>__init__()</code> qui alloue de la mémoire à leur objet : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/193ed94b-1b5b-47b4-9479-0d0e7c06807d/_322_-_Code2.png.png?t=1783802448"/></div><p class="paragraph" style="text-align:left;">Mais ce n&#39;est pas vrai.</p><p class="paragraph" style="text-align:left;">Quand on crée N&#39;IMPORTE QUEL objet en Python, la méthode <code>__init__()</code> n&#39;alloue JAMAIS de mémoire à cet objet.</p><p class="paragraph" style="text-align:left;">Comme son nom l&#39;indique, <code>__init__()</code> se contente d&#39;assigner des valeurs aux attributs d&#39;un objet, c&#39;est-à-dire d&#39;initialiser ses attributs.</p><p class="paragraph" style="text-align:left;">C&#39;est en réalité la méthode magique <code>__new__()</code> qui crée un nouvel objet et lui alloue de la mémoire.</p><p class="paragraph" style="text-align:left;">Pour mieux comprendre, prends l&#39;implémentation de classe ci-dessous. </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/42d182df-1a62-4f3c-ba32-91fe56f0f567/_322_-_Code3.png?t=1783802469"/></div><p class="paragraph" style="text-align:left;">Ici, on a implémenté la méthode <code>__new__()</code>, qui vérifie si les arguments passés sont bien de type entier (integer).</p><p class="paragraph" style="text-align:left;">Maintenant, si on essaie de créer un objet de cette classe, Python va d&#39;abord valider les vérifications spécifiées dans la méthode <code>__new__()</code>, et ne créer un nouvel objet que si les conditions spécifiées sont vraies.</p><p class="paragraph" style="text-align:left;">C&#39;est ce que montre l&#39;image ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/93c63fc3-05dd-4f5a-a075-5caf1ba3e0f1/_322_-_Code4.png.png?t=1783802506"/></div><p class="paragraph" style="text-align:left;">Un autre cas d&#39;usage populaire de la méthode <code>__new__()</code> est de définir des classes singleton, des classes qui ne peuvent avoir qu&#39;un seul objet.</p><p class="paragraph" style="text-align:left;">Par exemple, prends l&#39;implémentation de classe suivante : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/15a2a344-a342-4605-bc7f-8c2b7cd53cc1/_322_-_Code5.png?t=1783802528"/></div><p class="paragraph" style="text-align:left;">Dans le code ci-dessus, la méthode <code>__new__()</code> définit une variable de classe <code>_class_count</code>.</p><p class="paragraph" style="text-align:left;">Quand un nouvel objet est instancié, si la valeur de <code>_class_count</code> vaut 0, la valeur de <code>_class_count</code> est mise à jour à 1 et l&#39;objet est retourné.</p><p class="paragraph" style="text-align:left;">Après la création du premier objet, aucun nouvel objet ne peut plus jamais être créé, car la valeur de <code>_class_count</code> ne sera plus jamais égale à 0.</p><p class="paragraph" style="text-align:left;">C&#39;est ce que montre l&#39;image ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5a948814-8cb9-42ad-8227-44f14d905f25/_322_-_Code6.png?t=1783802643"/></div><p class="paragraph" style="text-align:left;">Si tu veux creuser la POO avancée en Python, voici une deep dive complète sur le sujet : </p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/poo-python-data-scientists-partie1?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=__init__-ne-cree-pas-tes-objets-en-python" target="_blank"><div class="embed__content"><p class="embed__title"> Programmation Orientée Objet avec Python pour les data scientists (Partie 1) </p><p class="embed__description"> Apprends la programmation orientée objet en Python : classes, objets, méthodes magiques et héritage, appliqués aux pipelines data pour data scientists. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/6d251a3f-b8eb-4ac5-98f5-8a30850be514/Mini-cours__15_-_Programmation_oriente%CC%81e_objet_avec_Python_pour_les_data_scientists.png?t=1772986035"/></a></div><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/poo-python-data-scientists-partie2?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=__init__-ne-cree-pas-tes-objets-en-python" target="_blank"><img class="embed__image embed__image--left" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/ea3c7186-f04b-4433-b550-86ff28efc9d8/Mini-cours__16_-_Code10.png?t=1772986036"/><div class="embed__content"><p class="embed__title"> Programmation orientée objet avec Python pour les data scientists (Partie 2) </p><p class="embed__description"> Approfondis la POO en Python : polymorphisme, encapsulation, classes avancées et optimisation pour des modèles de machine learning robustes. </p></div></a></div><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi de jouer :</b> quels sont d&#39;autres cas d&#39;usage de la méthode magique <code>__new__()</code> ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=59288259-8271-49ca-af8d-099bd9a78e7f&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Precision et Recall : la technique du Mindset</title>
  <description>🎯 Shot #321 - Un guide simple et intuitif pour ne plus jamais confondre ces deux métriques.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c3b75282-2b13-41b2-91b3-56b1852ed405/_321_-_Precision_et_Recall.png" length="36422" type="image/png"/>
  <link>https://www.monshotdata.com/p/precision-recall-technique-mindset</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/precision-recall-technique-mindset</guid>
  <pubDate>Fri, 10 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-10T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">J&#39;ai vu beaucoup de personnes avoir du mal à comprendre intuitivement la Precision et le Recall.</p><p class="paragraph" style="text-align:left;">Ces métriques, pourtant assez simples, en intimident plus d&#39;un.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e7c51e16-2fad-4319-bef6-a61912661f67/_321_-_Interpre%CC%81tation_Precision_et_Recall.png.png?t=1783346290"/></div><p class="paragraph" style="text-align:left;">Pourtant, adopter la &quot;technique du mindset&quot; peut énormément aider.</p><p class="paragraph" style="text-align:left;">Laisse-moi te guider aujourd&#39;hui.</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="precision">Precision</h2><p class="paragraph" style="text-align:left;">Formellement, la Precision répond à la question suivante :</p><p class="paragraph" style="text-align:left;"><b>&quot;Quelle proportion des prédictions positives étaient réellement positives ?&quot;</b></p><p class="paragraph" style="text-align:left;">Comprenons ça sous l&#39;angle du mindset.</p><p class="paragraph" style="text-align:left;">Quand on est dans un <b>Mindset Precision</b>, on ne se soucie pas de classifier correctement chaque sample positif.</p><p class="paragraph" style="text-align:left;">Mais il est important que chaque prédiction positive soit effectivement positive.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5df91778-69de-4def-91e7-5544a89ae1b2/_321_-_Mindset_Precision.png.png?t=1783346319"/></div><p class="paragraph" style="text-align:left;">Par exemple, imagine un système de recommandation de livres où une prédiction positive signifie qu&#39;on a aimé le livre recommandé.</p><p class="paragraph" style="text-align:left;">Dans un Mindset Precision, on accepte que le modèle ne recommande pas tous les bons livres du monde.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c1cfac49-e2c4-421f-9b73-cacefa57fa3d/_321_-_Recommandation_livres.png.png?t=1783346342"/><div class="image__source"><span class="image__source_text"><p><b>Mindset Precision :</b> Ce n&#39;est pas grave de passer à côté de certains bons livres, tant qu&#39;on ne recommande que des bons livres</p></span></div></div><p class="paragraph" style="text-align:left;">Mais ce qu&#39;il recommande doit être bon.</p><p class="paragraph" style="text-align:left;">Donc même si ce système ne recommandait qu&#39;un seul livre et qu&#39;on l&#39;a aimé, ça donne une Precision de 100%.</p><p class="paragraph" style="text-align:left;"><b>C&#39;est parce que ce qu&#39;il a classifié comme &quot;Positif&quot; était bien &quot;Positif&quot;.</b></p><p class="paragraph" style="text-align:left;">En résumé, dans un mindset haute Precision, toutes les prédictions positives doivent effectivement être positives.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="recall">Recall</h2><p class="paragraph" style="text-align:left;">Le Recall, c&#39;est un peu différent. Il répond à la question suivante :</p><p class="paragraph" style="text-align:left;"><b>&quot;Quelle proportion des vrais positifs a été correctement identifiée par le modèle ?&quot;</b></p><p class="paragraph" style="text-align:left;">Quand on est dans un <b>Mindset Recall</b>, on veut que chaque sample positif soit correctement classifié, sans exception.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a7985298-0b4b-4e36-976c-a212849be84d/_321_-_Mindset_Recall.png.png?t=1783673626"/></div><p class="paragraph" style="text-align:left;">Ce n&#39;est pas grave si certaines prédictions positives n&#39;étaient pas réellement positives.</p><p class="paragraph" style="text-align:left;">En revanche, tous les samples positifs doivent être classifiés comme positifs.</p><p class="paragraph" style="text-align:left;">Par exemple, imagine un système de présélection de candidats pour un entretien, basé sur leur CV. Une prédiction positive signifie que le candidat devrait être invité en entretien.</p><p class="paragraph" style="text-align:left;">Dans un Mindset Recall, tu acceptes que le modèle sélectionne quelques candidats incompétents.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/45253f5b-8906-4f9e-8e8a-4f9a95ed0156/_321_-_Classification_correcte_de_tous_les_samples_positifs.png.png?t=1783346436"/><div class="image__source"><span class="image__source_text"><p><b>Mindset Recall :</b> Concentre-toi simplement sur la classification correcte de tous les samples positifs</p></span></div></div><p class="paragraph" style="text-align:left;"></p><p class="paragraph" style="text-align:left;">Mais il ne doit surtout pas passer à côté d&#39;un candidat compétent.</p><p class="paragraph" style="text-align:left;">Donc même si ce système dit que tous les candidats (bons ou mauvais) sont aptes pour un entretien, ça donne un Recall de 100%.</p><p class="paragraph" style="text-align:left;">C&#39;est parce qu&#39;il n&#39;a manqué aucun des samples positifs.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">La métrique à choisir dépend entièrement de ce qui compte pour le problème en question :</p><p class="paragraph" style="text-align:left;"><b>Optimise la Precision si :</b></p><ol start="1"><li><p class="paragraph" style="text-align:left;">Tu veux obtenir UNIQUEMENT des prédictions positives de haute qualité.</p></li><li><p class="paragraph" style="text-align:left;">Tu acceptes que certains samples de qualité (ou positifs) soient laissés de côté.</p></li></ol><p class="paragraph" style="text-align:left;"><b>Optimise le Recall si :</b></p><ol start="1"><li><p class="paragraph" style="text-align:left;">Tu veux identifier TOUS les samples de qualité (ou positifs) correctement.</p></li><li><p class="paragraph" style="text-align:left;">Tu acceptes que certains samples de moindre qualité (ou négatifs) se glissent dans le lot.</p></li></ol><p class="paragraph" style="text-align:left;">Mais en pratique, optimiser uniquement pour un Recall élevé n&#39;est pas très utile.</p><p class="paragraph" style="text-align:left;">C&#39;est parce que même si tu implémentes une simple fonction qui prédit toujours &quot;positif&quot;, le classifieur aura quand même un Recall de 100%. Car notre modèle naïf classifie correctement toutes les instances positives.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/30dc0cc6-0703-436d-b654-f691afef4e43/_321_-_100__de_Recall.png?t=1783346487"/></div><p class="paragraph" style="text-align:left;">En revanche, optimiser pour une Precision élevée demande un vrai travail d&#39;ingénierie.</p><p class="paragraph" style="text-align:left;">J&#39;espère que c&#39;était utile :)</p><hr class="content_break"><p class="paragraph" style="text-align:left;">👉 À toi : quelle analogie as-tu utilisée la première fois pour comprendre la Precision et le Recall ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=4b7652be-65f4-4d8f-9ed5-f0a6001fa334&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>CUDA de A à Z : comprendre ce qui se cache derrière model.cuda()</title>
  <description>👀​ Mini-cours #35 - Un guide pratique pour percer le fonctionnement interne des GPU, avec du code CUDA C/C++ à exécuter toi-même.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/115be2e5-9795-45fb-9a82-3629c105fdd3/Mini-cours__35_-_Deep_Dive_CUDA.png" length="101170" type="image/png"/>
  <link>https://www.monshotdata.com/p/cuda-programming-comprendre-acceleration-gpu</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/cuda-programming-comprendre-acceleration-gpu</guid>
  <pubDate>Wed, 08 Jul 2026 14:45:00 +0000</pubDate>
  <atom:published>2026-07-08T14:45:00Z</atom:published>
    <category><![CDATA[Scaling &amp; Calcul Distribué]]></category>
    <category><![CDATA[Pro]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#f2eafe;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:2.0px 2.0px 2.0px 2.0px;"><p class="paragraph" style="text-align:left;"><span style="text-decoration:underline;"><b>Psst... Contenu Exclusif Réservé aux Membres !</b></span><br><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Ce mini-cours fait partie de notre espace premium. Rejoins dès maintenant le </span><b>Cercle des Experts</b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;"> pour débloquer l’intégralité de nos ressources, analyses approfondies et guides pratiques.</span><br><b>👉 </b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Clique ici pour découvrir les avantages et t’inscrire : </span><b><a class="link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=cuda-de-a-a-z-comprendre-ce-qui-se-cache-derriere-model-cuda" target="_blank" rel="noopener noreferrer nofollow" style="color: #2563eb">Page d’adhésion</a></b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">.</span></p></div><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#222222;font-family:Poppins, Helvetica, sans-serif, serif, EmojiFont;font-size:16px;">⏱️ </span><i><b>Temps de lecture</b></i><i> : 40-50 minutes</i></p></div><h2 class="heading" style="text-align:left;" id="introduction">Introduction</h2><p class="paragraph" style="text-align:left;">Grâce aux avancées des frameworks open-source comme PyTorch, exploiter un GPU pour accélérer l&#39;entraînement d&#39;un modèle de deep learning tient en une seule ligne, comme illustré ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cd043775-c547-4e39-a80c-2c0fd0fb3003/Mini-cours__35_-_Code1.png.png?t=1783500140"/></div><p class="paragraph" style="text-align:left;">Si cette encapsulation est aussi simple que possible, l&#39;<b>implémentation sous-jacente</b>, celle qui permet aux GPU d&#39;accélérer les calculs, reste un mystère pour beaucoup.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b9955604-a349-4d29-80a0-0df6844169c1/Mini-cours__35_-_Que_se_passe-t-il_sous_le_capot_.png.png?t=1783500176"/></div><p class="paragraph" style="text-align:left;">Plus précisément : que se passe-t-il réellement quand on appelle <code>.cuda()</code> ?</p><p class="paragraph" style="text-align:left;">Dans ce deep dive, on va décortiquer la mécanique de la programmation GPU.</p><p class="paragraph" style="text-align:left;">Plus précisément, on va comprendre comment CUDA, une interface de programmation développée par NVIDIA, permet aux développeurs d&#39;exécuter des processus sur leurs GPU, et <b>comment cette implémentation fonctionne en coulisses</b>.</p><p class="paragraph" style="text-align:left;">Pour ça, on va faire un vrai travail pratique de programmation CUDA et implémenter des versions parallélisées de plusieurs opérations qu&#39;on utilise en permanence en deep learning.</p><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="questce-que-cuda">Qu&#39;est-ce que CUDA ?</h2><p class="paragraph" style="text-align:left;">En résumé, CUDA (<i>Compute Unified Device Architecture</i>) est une plateforme de calcul parallèle et un modèle d&#39;interface de programmation (API) créés par NVIDIA.</p><p class="paragraph" style="text-align:left;">Il permet aux développeurs d&#39;utiliser un GPU compatible CUDA pour du calcul généraliste.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c40168c8-1622-41b8-815f-25f7807192ea/Mini-cours__35_-_CUDA.png.png?t=1783500284"/></div><div class="section" style="background-color:#f1e8fb;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:left;">💡 Pour donner un peu de contexte : le calcul généraliste, c&#39;est le fait de détourner une capacité de calcul vers un usage large, au-delà de sa fonction spécialisée d&#39;origine. Dans le cas des GPU, conçus à la base pour le rendu graphique dans les jeux vidéo, le calcul généraliste permet de les réorienter vers des tâches intensives en calcul, sans lien direct avec le graphisme.</p></div><p class="paragraph" style="text-align:left;">Pour exploiter la puissance de calcul du GPU, CUDA fournit une interface implémentée en C/C++. Elle permet d&#39;accéder à la mémoire du GPU et d&#39;y exécuter des opérations de calcul.</p><p class="paragraph" style="text-align:left;">Dans le contexte du deep learning, ce sont typiquement des opérations mathématiques et générales comme :</p><ul><li><p class="paragraph" style="text-align:left;">Additionner des matrices/vecteurs</p></li><li><p class="paragraph" style="text-align:left;">Multiplier des matrices</p></li><li><p class="paragraph" style="text-align:left;">Transformer une matrice en lui appliquant une fonction, comme une fonction d&#39;activation, un dropout, etc.</p></li><li><p class="paragraph" style="text-align:left;">Déplacer des données du CPU vers le GPU, puis les rapatrier</p></li><li><p class="paragraph" style="text-align:left;">Et bien plus encore</p></li></ul><p class="paragraph" style="text-align:left;">Autrement dit : tout comme Pandas permet aux développeurs d&#39;interagir facilement avec des données tabulaires via des structures et opérations haut niveau, CUDA offre un niveau d&#39;abstraction équivalent, mais pour le calcul sur GPU NVIDIA.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/77f5e9f6-085b-4e92-8a0c-dbc254615d86/Mini-cours__35_-_Pandas_vs._CUDA.png.png?t=1783500373"/></div><p class="paragraph" style="text-align:left;">En masquant la complexité sous-jacente liée au GPU (gestion de la mémoire, gestion des threads, gestion des blocs), CUDA permet aux développeurs de se concentrer sur le problème de calcul à résoudre plutôt que sur les subtilités du matériel sur lequel il tourne.</p><p class="paragraph" style="text-align:left;">Bien sûr, comme évoqué plus haut, CUDA fournit une interface C/C++, et les frameworks de deep learning comme PyTorch ont simplifié tout ça en construisant un wrapper Python autour : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e9f003b5-4e05-4159-aef6-96edb40e5d58/Mini-cours__35_-_API_Python_avec_Python.png.png?t=1783500456"/></div><p class="paragraph" style="text-align:left;">Donc quand on développe des modèles de deep learning, on utilise une API Python qui, en coulisses, s&#39;appuie sur des instructions C/C++ fournies par CUDA pour dialoguer avec le GPU.</p><p class="paragraph" style="text-align:left;">Pour être clair, l&#39;objectif de ce dossier est de comprendre ce chemin CUDA → instructions GPU, et comment il est implémenté.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6f3135ea-e725-49c0-964f-421611376907/Mini-cours__35_-_Instructions_GPU_avec_CUDA.png.png?t=1783500564"/></div><p class="paragraph" style="text-align:left;">Une certaine aisance en C/C++ est un plus, mais ce n&#39;est pas indispensable : le design de l&#39;API est plutôt intuitif. Cela dit, je t&#39;apporterai des explications complémentaires à chaque étape si tu n&#39;as jamais touché au C++.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="le-problme-avec-les-cpu">Le problème avec les CPU</h2><p class="paragraph" style="text-align:left;">Quand il s&#39;agit de paralléliser, l&#39;approche traditionnelle avec les CPU repose sur les threads (fils d&#39;exécution), qui portent des instructions que le processeur peut exécuter indépendamment.</p><p class="paragraph" style="text-align:left;">Prenons par exemple cette simple boucle for en C, qui réalise les opérations d&#39;une couche linéaire classique : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/69de0dd0-1022-4861-806c-36bcd297c2e8/Mini-cours__35_-_Code2.png.png?t=1783500638"/></div><p class="paragraph" style="text-align:left;">Observe cette boucle for dans le code ci-dessus. Elle parcourt les éléments des tableaux un par un, calcule le résultat individuel, et le stocke dans le tableau de sortie.</p><p class="paragraph" style="text-align:left;">Si tu regardes de près, toutes ces opérations individuelles sont indépendantes les unes des autres.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9a63af9d-c6ce-48cd-910d-11f0f6862361/Mini-cours__35_-_Ope%CC%81rations_individuelles_inde%CC%81pendantes.png?t=1783500709"/><div class="image__source"><span class="image__source_text"><p>la i-ème opération ne dépend pas de la j-ème opération</p></span></div></div><p class="paragraph" style="text-align:left;">Elles pourraient donc être exécutées en parallèle. Pourtant, l&#39;implémentation ci-dessus utilise une approche séquentielle : chaque opération attend que la précédente se termine avant de démarrer.</p><p class="paragraph" style="text-align:left;">Les CPU modernes peuvent gérer plusieurs threads simultanément grâce à des techniques comme <b>le multi-threading</b>. On peut donc s&#39;en servir pour que la boucle génère plusieurs threads, potentiellement un par cœur, afin de traiter différentes parties du tableau en même temps.</p><p class="paragraph" style="text-align:left;">Et c&#39;est assez intuitif : plus on ajoute de threads, plus le niveau de parallélisme qu&#39;on peut atteindre est élevé.</p><p class="paragraph" style="text-align:left;">En deep learning, les choses sont différentes.</p><p class="paragraph" style="text-align:left;">Les briques de base des modèles de deep learning, les vecteurs et les matrices, peuvent contenir des millions d&#39;éléments.</p><p class="paragraph" style="text-align:left;">Or, par nature, les CPU sont limités dans leur degré de parallélisme à cause d&#39;un nombre de cœurs restreint (même les CPU grand public haut de gamme dépassent rarement 16 cœurs).</p><p class="paragraph" style="text-align:left;">Les GPU, eux, sont des architectures modernes capables de faire tourner des millions de threads en parallèle. Ça améliore considérablement les performances de ces opérations mathématiques quand on manipule des vecteurs et des matrices de très grande taille.</p><h3 class="heading" style="text-align:left;" id="un-exemple-pour-illustrer">Un exemple pour illustrer</h3><p class="paragraph" style="text-align:left;">Prenons l&#39;opération de multiplication matricielle ci-dessous, omniprésente en deep learning : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/e19c02db-fbc3-4ebf-a432-51a5f068d450/Mini-cours__35_-_Une_multiplication_matricielle.png.png?t=1783500804"/></div><p class="paragraph" style="text-align:left;">Fondamentalement, une multiplication matricielle n&#39;est qu&#39;une série de produits scalaires indépendants entre vecteurs, comme illustré dans l&#39;animation ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c2b6f91a-b8b8-4127-a344-4c45ee01a92a/Mini-cours__35_-_multiplication-matrices.gif?t=1783500832"/></div><ul><li><p class="paragraph" style="text-align:left;">La 1ʳᵉ ligne de la matrice de gauche est multipliée avec :</p><ul><li><p class="paragraph" style="text-align:left;">La 1ʳᵉ colonne de la matrice de droite</p></li><li><p class="paragraph" style="text-align:left;">La 2ᵉ colonne de la matrice de droite</p></li><li><p class="paragraph" style="text-align:left;">La 3ᵉ colonne de la matrice de droite</p></li></ul></li><li><p class="paragraph" style="text-align:left;">Et ainsi de suite</p></li><li><p class="paragraph" style="text-align:left;">La 2ᵉ ligne de la matrice de gauche est multipliée avec :</p><ul><li><p class="paragraph" style="text-align:left;">La 1ʳᵉ colonne de la matrice de droite</p></li><li><p class="paragraph" style="text-align:left;">La 2ᵉ colonne de la matrice de droite</p></li><li><p class="paragraph" style="text-align:left;">La 3ᵉ colonne de la matrice de droite</p></li><li><p class="paragraph" style="text-align:left;">Et ainsi de suite</p></li></ul></li><li><p class="paragraph" style="text-align:left;">Et ainsi de suite...</p></li></ul><p class="paragraph" style="text-align:left;">Si tu regardes bien, toutes ces opérations sont indépendantes les unes des autres. Elles pourraient donc, en théorie, toutes être exécutées en parallèle.</p><p class="paragraph" style="text-align:left;">Mais comme on l&#39;a vu, les CPU disposant d&#39;un nombre de threads assez limité, ils ne sont pas idéaux pour exploiter tout le potentiel de parallélisation de ces multiplications matricielles.</p><p class="paragraph" style="text-align:left;">Autrement dit, les CPU ne gèrent généralement qu&#39;une poignée de dizaines de threads simultanément, ce qui limite leur efficacité pour exécuter un grand nombre d&#39;opérations indépendantes en même temps, comme celles requises par des multiplications matricielles à grande échelle.</p><h3 class="heading" style="text-align:left;" id="comment-les-gpu-aidentils">Comment les GPU aident-ils ?</h3><p class="paragraph" style="text-align:left;">Il faut clarifier un point important : les CPU ne sont pas &quot;mauvais&quot;.</p><p class="paragraph" style="text-align:left;">Il y a une raison pour laquelle tous les ordinateurs modernes embarquent systématiquement un CPU, mais pas nécessairement un GPU &quot;rapide&quot;. C&#39;est parce que le CPU et le GPU sont conçus pour atteindre des objectifs complètement différents.</p><p class="paragraph" style="text-align:left;">Pour commencer, les calculs CPU sont généralement plus rapides que ceux du GPU pour <b>une opération unique</b>. Autrement dit, ils sont conçus pour exécuter rapidement une séquence d&#39;opérations mono-thread. Pour maintenir cette vitesse, ils ne peuvent exécuter qu&#39;un nombre limité de threads en parallèle.</p><p class="paragraph" style="text-align:left;">À l&#39;inverse, les GPU sont conçus pour exécuter des millions de threads en parallèle, au prix de la vitesse de chaque thread pris individuellement.</p><p class="paragraph" style="text-align:left;">Donc même si un thread met moins de temps à s&#39;exécuter sur un CPU, le fait que les GPU puissent en exécuter des millions en parallèle démultiplie considérablement le temps d&#39;exécution global.</p><h3 class="heading" style="text-align:left;" id="une-analogie-tire-de-la-vraie-vie">Une analogie tirée de la vraie vie</h3><p class="paragraph" style="text-align:left;">Une analogie que j&#39;ai entendue il y a des années, quand j&#39;ai découvert ces concepts, compare le CPU à une voiture de F1 et le GPU à un bus.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/947c53a5-7e29-4046-b486-418a171e6ffb/Mini-cours__35_-_CPU_vs._GPU.png.png?t=1783500957"/></div><p class="paragraph" style="text-align:left;">Si l&#39;objectif est de déplacer une seule personne d&#39;un point A à un point B, alors la voiture de F1, c&#39;est-à-dire le CPU, sera le choix idéal.</p><p class="paragraph" style="text-align:left;">En revanche, si l&#39;objectif est de déplacer beaucoup de personnes d&#39;un point à un autre, alors le bus, c&#39;est-à-dire le GPU, sera le choix idéal. Et ce, même si une F1 mettra moins de temps à parcourir la distance entre A et B.</p><p class="paragraph" style="text-align:left;">Le bus peut transporter tout le monde en un seul trajet, là où la F1 devrait multiplier les allers-retours.</p><hr class="content_break"><div class="section" style="background-color:#1B3A6B;border-color:#F7931E;border-radius:8px;border-style:solid;border-width:3px;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;">💡<span style="color:#F9FAFB;"> En continuant, tu vas découvrir : </span></p><ul><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Les trois composants fondamentaux de CUDA : host, device et kernel, et comment ils s&#39;articulent</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Comment naviguer la hiérarchie thread → block → grid, et calculer l&#39;index global d&#39;un thread en 1D comme en 2D</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">L&#39;implémentation pas à pas d&#39;une couche linéaire en CUDA C/C++, du </span><span style="color:#F9FAFB;"><code>cudaMalloc</code></span><span style="color:#F9FAFB;"> au </span><span style="color:#F9FAFB;"><code>cudaMemcpy</code></span><span style="color:#F9FAFB;">, jusqu&#39;à la compilation avec </span><span style="color:#F9FAFB;"><code>nvcc</code></span><span style="color:#F9FAFB;"> sur Google Colab</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Comment structurer une addition et une multiplication de matrices avec des configurations de threads en 2D grâce au type </span><span style="color:#F9FAFB;"><code>dim3</code></span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Pourquoi ajouter des blocs change tout quand tu dépasses la limite de threads par bloc</span></p></li></ul><p class="paragraph" style="text-align:left;"></p></div><div class="paywall"><hr class="paywall__break"/><div class="paywall__content"><h2 class="paywall__header"> La suite de ce mini-cours est réservée aux membres du Cercle des Experts. </h2><p class="paywall__description"> Tu as déjà le début. Pour accéder à l’explication complète et à tous les contenus avancés, rejoins le Cercle des Experts dès maintenant. </p><p class="paywall__links"><a class="paywall__upgrade_link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=cuda-de-a-a-z-comprendre-ce-qui-se-cache-derriere-model-cuda">Rejoindre le Cercle des Experts</a> Translation missing: en.app.shared.conjuction.or <a class="paywall__login_link" href="https://www.monshotdata.com/login?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=cuda-de-a-a-z-comprendre-ce-qui-se-cache-derriere-model-cuda">Sign In</a></p><div class="paywall__upsell"><div class="paywall__upsell_header"><h3> En devenant membre, tu débloques </h3></div><ul class="paywall__upsell_features"><li class="paywall__upsell_feature"> L’intégralité de ce mini-cours (sans coupure) </li><li class="paywall__upsell_feature"> Tous les mini-cours archivés et les ressources associées </li><li class="paywall__upsell_feature"> 1 nouveau mini-cours chaque semaine pour progresser en continu </li></ul></div></div></div></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=3972f347-aa0e-4645-be88-16cafaba604b&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Ce que la plupart des devs ignorent sur les dictionnaires Python</title>
  <description>🎯 Shot #320 -  Identité d&#39;objet vs. équivalence de hash : le détail qui change tout.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/31d31910-3568-4e53-8def-80b87503e508/_320_-_Code11.png.png" length="235622" type="image/png"/>
  <link>https://www.monshotdata.com/p/dictionnaires-python-piege-equivalence-hash</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/dictionnaires-python-piege-equivalence-hash</guid>
  <pubDate>Mon, 06 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-06T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Python]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Même si Python est probablement l&#39;un des langages de programmation les plus faciles pour débuter, il y a BEAUCOUP de choses qui le rendent parfois étrange et contre-intuitif.</p><p class="paragraph" style="text-align:left;">Aujourd&#39;hui, je veux te partager une particularité des dictionnaires Python que la plupart des développeurs Python ignorent.</p><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Supposons qu&#39;on déclare le dictionnaire Python suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4bae0734-c651-465c-b9c6-01b99ce53e27/_320_-_Code1.png?t=1783255086"/></div><p class="paragraph" style="text-align:left;">On ajoute quatre clés lors de cette déclaration de dictionnaire :</p><ul><li><p class="paragraph" style="text-align:left;">Le type <code>Integer 1</code></p></li><li><p class="paragraph" style="text-align:left;">Le type <code>Float 1.0</code></p></li><li><p class="paragraph" style="text-align:left;">Le type <code>Boolean True</code></p></li><li><p class="paragraph" style="text-align:left;">Le type <code>String &#39;1&#39;</code></p></li></ul><p class="paragraph" style="text-align:left;">Ces quatre clés sont quatre objets différents, ce qu&#39;on peut aussi vérifier en affichant leurs identifiants d&#39;objet respectifs avec la méthode <code>id()</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8b068d0f-1cf3-4a2a-bfb1-5e850f7329a5/_320_-_Code2.png.png?t=1783255124"/></div><p class="paragraph" style="text-align:left;">On pourrait donc s&#39;attendre à ce que le dictionnaire final contienne quatre clés.</p><p class="paragraph" style="text-align:left;">Pourtant, quand on affiche le dictionnaire ci-dessus, on constate <b>qu&#39;il n&#39;y a que deux clés</b> : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7fe693e9-0edb-4fe7-ae30-d1e8bdd72e1c/_320_-_Code3.png.png?t=1783255388"/></div><p class="paragraph" style="text-align:left;">Où sont passées les deux autres clés ?</p><p class="paragraph" style="text-align:left;">Qu&#39;est-ce qui nous échappe ?</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="fonctionnement-interne-dun-dictionn">Fonctionnement interne d&#39;un dictionnaire Python</h2><p class="paragraph" style="text-align:left;">La plupart des développeurs Python pensent que les dictionnaires recherchent/insèrent/suppriment une clé en se basant sur l&#39;ID de l&#39;objet ajouté comme clé.</p><p class="paragraph" style="text-align:left;">Mais ce n&#39;est pas vrai.</p><p class="paragraph" style="text-align:left;">En réalité, les dictionnaires font cela en utilisant l&#39;<b>équivalence de hash</b>, calculée via la méthode <code>hash()</code>.</p><p class="paragraph" style="text-align:left;">Ainsi, si deux objets ont la même valeur de hash, le dictionnaire les considérera comme des clés identiques.</p><p class="paragraph" style="text-align:left;">C&#39;est exactement ce qu&#39;on observe avec les objets « <code>Integer 1</code> », « <code>Float 1.0</code> » et « <code>Boolean True</code> ».</p><p class="paragraph" style="text-align:left;">Comme illustré ci-dessous, ces trois objets ont la même valeur de hash :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/63042c64-888c-4285-be21-5937fcccf948/_320_-_Code4.png.png?t=1783255191"/></div><p class="paragraph" style="text-align:left;">En conséquence, un dictionnaire Python les considère comme des clés identiques, bien qu&#39;il s&#39;agisse d&#39;objets totalement différents.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Un point important à noter : le dictionnaire final conserve la clé « <code>Integer 1</code> », mais sa valeur est celle correspondant à la clé « <code>Boolean True</code> ».</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2d3ed5e3-282d-49ed-8943-b99e7a88809a/_320_-_Code5.png.png?t=1783255426"/></div><p class="paragraph" style="text-align:left;">Cela s&#39;explique par l&#39;ordre dans lequel on a spécifié les clés lors de la déclaration du dictionnaire :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4bae0734-c651-465c-b9c6-01b99ce53e27/_320_-_Code1.png?t=1783255087"/></div><p class="paragraph" style="text-align:left;">Décomposons les étapes :</p><ul><li><p class="paragraph" style="text-align:left;">Quand l&#39;objet dictionnaire est créé, le dictionnaire est vide. À partir de là, les clés vont être ajoutées une par une.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/28b7c3c6-83d4-4ecd-b78a-6e8df62b76a0/_320_-_Code6.png?t=1783255480"/></div><ul><li><p class="paragraph" style="text-align:left;">D&#39;abord, « <code>Integer 1</code> » est ajouté, et le dictionnaire devient :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b2b68855-1812-40f5-b31d-b962ef7b0775/_320_-_Code7.png.png?t=1783255511"/></div><ul><li><p class="paragraph" style="text-align:left;">Ensuite, en ajoutant « <code>Float 1.0</code> », Python détecte une équivalence de hash avec la clé existante « <code>Integer 1</code> ». La clé existante (« <code>Integer 1</code> ») est donc conservée, mais sa valeur est mise à jour :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/be95b8c8-3e16-4db0-b729-3725fc53b239/_320_-_Code8.png.png?t=1783255539"/></div><ul><li><p class="paragraph" style="text-align:left;">En continuant, lors de l&#39;ajout de « <code>Boolean True</code> », une nouvelle équivalence de hash se produit avec la clé existante « <code>Integer 1</code> ». Encore une fois, la clé existante (« <code>Integer 1</code> ») est conservée, mais sa valeur est mise à jour :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/156e1e29-f800-4324-aad8-5ff6df7ee700/_320_-_Code9.png.png?t=1783255584"/></div><ul><li><p class="paragraph" style="text-align:left;">Enfin, en ajoutant « <code>String 1</code> », aucune équivalence de hash ne se produit, et une nouvelle clé est ajoutée, ce qui nous donne le dictionnaire suivant :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f6d28c6c-2c21-4c26-930c-2dffcb3aeb04/_320_-_Code10.png.png?t=1783255611"/></div><p class="paragraph" style="text-align:left;">On peut valider ce raisonnement en changeant l&#39;ordre dans lequel on a spécifié les clés lors de la déclaration du dictionnaire :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/31d31910-3568-4e53-8def-80b87503e508/_320_-_Code11.png.png?t=1783255646"/></div><p class="paragraph" style="text-align:left;">Cette fois, on obtient un résultat différent, mais il est cohérent avec le raisonnement ci-dessus.</p><hr class="content_break"><h3 class="heading" style="text-align:left;" id="ce-quil-faut-retenir">Ce qu&#39;il faut retenir</h3><p class="paragraph" style="text-align:left;">Contrairement à une croyance répandue, les dictionnaires Python ne recherchent/insèrent/suppriment jamais les clés en se basant sur l&#39;identité des objets. Ils utilisent l&#39;équivalence de hash.</p><p class="paragraph" style="text-align:left;">Consulte ces autres shots data pour découvrir d&#39;autres particularités ou subtilités techniques de Python souvent mal interprétées :</p><ul><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/python-piege-arguments-mutables?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=ce-que-la-plupart-des-devs-ignorent-sur-les-dictionnaires-python" target="_blank" rel="noopener noreferrer nofollow">Une fonctionnalité vicieuse de Python que beaucoup de développeurs ignorent</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/immutabilite-tuples-python?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=ce-que-la-plupart-des-devs-ignorent-sur-les-dictionnaires-python" target="_blank" rel="noopener noreferrer nofollow">L&#39;erreur la plus courante sur l&#39;immutabilité des tuples</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/liste-cle-dictionnaire-python?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=ce-que-la-plupart-des-devs-ignorent-sur-les-dictionnaires-python" target="_blank" rel="noopener noreferrer nofollow">Comment Python nous empêche d&#39;ajouter une liste comme clé de dictionnaire</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/python-del?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=ce-que-la-plupart-des-devs-ignorent-sur-les-dictionnaires-python" target="_blank" rel="noopener noreferrer nofollow">Une idée reçue courante sur la suppression d&#39;objets en Python</a></p></li><li><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/boucle-for-vs-list-comprehension-une-diff-rence-fondamentale?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=ce-que-la-plupart-des-devs-ignorent-sur-les-dictionnaires-python" target="_blank" rel="noopener noreferrer nofollow">Un for-loop et une list comprehension sont fondamentalement différents au niveau du scope</a></p></li></ul><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi :</b> quels sont les autres concepts techniques de Python que la plupart des développeurs interprètent mal ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=ef43deb2-9bbe-4d48-8b02-281b22e7520a&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Deux Techniques Simples pour Booster les Modèles kNN</title>
  <description>🎯 Shot #319 - Comment contourner la sensibilité au paramètre k et mieux gérer les classes minoritaires ?</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d9fc9444-5bee-4393-a817-4ba0f70738bb/_319_-_Une_technique_sous-estime%CC%81e_pour_booster_les_kNN.png.png" length="738646" type="image/png"/>
  <link>https://www.monshotdata.com/p/booster-modeles-knn-deux-techniques</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/booster-modeles-knn-deux-techniques</guid>
  <pubDate>Fri, 03 Jul 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-07-03T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Une des choses qui me rend toujours un peu prudent et sceptique quand j&#39;utilise kNN, c&#39;est sa HAUTE sensibilité au paramètre <code>k</code>.</p><p class="paragraph" style="text-align:left;">Pour mieux comprendre, considère ce dataset fictif en 2D ci-dessous. Le point rouge est une instance de test pour laquelle on veut générer une prédiction avec kNN.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/720a0bf8-40b9-49e2-a8d4-465122b12f13/_319_-_kNN-1.png.png?t=1783068635"/></div><p class="paragraph" style="text-align:left;">Disons qu&#39;on fixe <code>k=7</code>.</p><p class="paragraph" style="text-align:left;">La prédiction pour l&#39;instance rouge se fait en deux étapes :</p><ol start="1"><li><p class="paragraph" style="text-align:left;">D&#39;abord, on identifie les <code>7</code> plus proches voisins du point rouge.</p></li><li><p class="paragraph" style="text-align:left;">Ensuite, on l&#39;assigne à la classe la plus représentée parmi ces 7 voisins.</p></li></ol><p class="paragraph" style="text-align:left;">C&#39;est illustré ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ce084ff7-9c8e-4bf3-bee6-10d4f754362c/_319_-_kNN-2.png.png?t=1783068649"/></div><p class="paragraph" style="text-align:left;">Le problème, c&#39;est que <b>l&#39;étape 2</b> repose entièrement sur la notion de contribution de classe : la classe qui contribue le plus parmi les <code>k</code> plus proches voisins est assignée au point.</p><p class="paragraph" style="text-align:left;">Mais ça peut échouer lamentablement dans certains cas, surtout quand une classe a peu d&#39;échantillons.</p><p class="paragraph" style="text-align:left;">Par exemple, comme montré ci-dessous, avec <code>k=7</code>, le point rouge ne pourra <b>JAMAIS</b> être assigné à la classe jaune, peu importe à quel point il est proche de ce cluster :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5af3b3eb-c0a2-44ef-8059-cf6553de964a/_319_-_kNN-3.png.png?t=1783068662"/></div><p class="paragraph" style="text-align:left;">S&#39;il est facile d&#39;ajuster visuellement l&#39;hyperparamètre <code>k</code> dans cette démo, cette approche est inapplicable sur des datasets en haute dimension.</p><p class="paragraph" style="text-align:left;">Il existe deux façons de résoudre ce problème.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="solution-1-utiliser-un-k-nn-pondr-p">Solution #1 : Utiliser un kNN pondéré par la distance</h2><p class="paragraph" style="text-align:left;">Les kNN pondérés par la distance sont une alternative bien plus robuste aux kNN traditionnels.</p><p class="paragraph" style="text-align:left;">Comme leur nom l&#39;indique, à l&#39;étape 2, ils prennent en compte la distance au plus proche voisin.</p><p class="paragraph" style="text-align:left;">Résultat : plus un voisin est proche, plus il aura d&#39;impact sur la prédiction finale.</p><p class="paragraph" style="text-align:left;">Son efficacité est évidente sur l&#39;image ci-dessous.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/d9fc9444-5bee-4393-a817-4ba0f70738bb/_319_-_Une_technique_sous-estime%CC%81e_pour_booster_les_kNN.png.png?t=1783068615"/></div><ul><li><p class="paragraph" style="text-align:left;">Sur le premier graphique, le kNN traditionnel (avec k=7) ne peut jamais prédire la classe bleue.</p></li><li><p class="paragraph" style="text-align:left;">Sur le second graphique, le kNN pondéré par la distance se montre bien plus robuste dans sa prédiction.</p></li></ul><p class="paragraph" style="text-align:left;">D&#39;après mon observation, un kNN pondéré par la distance fonctionne généralement bien mieux qu&#39;un kNN traditionnel. Et intuitivement, ça se tient.</p><p class="paragraph" style="text-align:left;">Pourtant, ça peut passer inaperçu parce que, par défaut, l&#39;implémentation kNN de sklearn utilise une pondération &quot;uniform&quot;.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a0c5b043-3cf8-441f-bb0b-ac9ecb2bd748/_319_-_KNeighborsClassifier.png.png?t=1783068698"/></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="solution-2-mettre-jour-dynamiquemen">Solution #2 : Mettre à jour dynamiquement l&#39;hyperparamètre k</h2><p class="paragraph" style="text-align:left;">Reprenons la démo ci-dessus :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5af3b3eb-c0a2-44ef-8059-cf6553de964a/_319_-_kNN-3.png.png?t=1783068662"/></div><p class="paragraph" style="text-align:left;">Ici, on pourrait arguer qu&#39;il ne faut jamais fixer l&#39;hyperparamètre k à une valeur supérieure au nombre minimum d&#39;échantillons d&#39;une classe dans le dataset.</p><p class="paragraph" style="text-align:left;">Bien sûr, je suis d&#39;accord avec ça, dans une certaine mesure.</p><p class="paragraph" style="text-align:left;">Mais laisse-moi t&#39;expliquer l&#39;inconvénient de cette approche.</p><p class="paragraph" style="text-align:left;">Fixer une valeur très basse de <code>k</code> peut être très problématique dans le cas de datasets extrêmement déséquilibrés.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6c520db5-a0df-4cca-ae57-735e2cc15581/_319_-_Distribution_des_classes.png.png?t=1783068765"/></div><p class="paragraph" style="text-align:left;">Pour te donner plus de contexte, j&#39;ai personnellement utilisé kNN sur des datasets qui ne contenaient qu&#39;une ou deux instances pour une classe donnée dans le training set.</p><p class="paragraph" style="text-align:left;">Et j&#39;ai constaté que fixer un <code>k</code> bas (disons 1 ou 2) menait à des performances sous-optimales parce que le modèle n&#39;évaluait pas les patterns de voisinage de manière aussi globale que lorsqu&#39;un <code>k</code> élevé était utilisé.</p><p class="paragraph" style="text-align:left;">Autrement dit, fixer une valeur relativement plus grande de <code>k</code> donne généralement des prédictions plus éclairées qu&#39;avec des valeurs basses.</p><p class="paragraph" style="text-align:left;">Mais on vient de voir que si on fixe un <code>k</code> élevé, la classe majoritaire peut dominer le résultat de classification :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5af3b3eb-c0a2-44ef-8059-cf6553de964a/_319_-_kNN-3.png.png?t=1783068662"/></div><p class="paragraph" style="text-align:left;"><b>Pour résoudre ce problème, j&#39;ai trouvé que mettre à jour dynamiquement l&#39;hyperparamètre </b><code>k</code><b> était bien plus efficace.</b></p><p class="paragraph" style="text-align:left;">Plus précisément, cette approche se décompose en trois étapes.</p><p class="paragraph" style="text-align:left;">Pour chaque instance de test :</p><ol start="1"><li><p class="paragraph" style="text-align:left;">Commence avec une valeur standard de <code>k</code> comme d&#39;habitude et identifie les <code>k</code> plus proches voisins.</p></li><li><p class="paragraph" style="text-align:left;">Ensuite, mets à jour la valeur de <code>k</code> comme suit : </p></li></ol><ul><li><p class="paragraph" style="text-align:left;"><b>Pour toutes les classes uniques présentes parmi les </b><code>k</code><b> plus proches voisins</b>, trouve le nombre total d&#39;instances d&#39;entraînement qu&#39;elles contiennent.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/39349e4e-6896-4bf5-a42a-ceb2fa13a7ea/_319_-_kNN-4.png.png?t=1783068824"/></div><ul><li><p class="paragraph" style="text-align:left;">Mets à jour la valeur de <code>k</code> en :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cd9ae485-56e0-4e46-9aa9-65f1ca474163/_319_-_mettre_a%CC%80_jour_la_valeur_de_k.png?t=1783068853"/></div><ol start="3"><li><p class="paragraph" style="text-align:left;">Effectue maintenant l<b>e vote majoritaire uniquement sur les </b><code>k&#39;</code><b> premiers voisins</b>.</p></li></ol><p class="paragraph" style="text-align:left;">Intuitivement, ça se tient aussi :</p><ul><li><p class="paragraph" style="text-align:left;">Si une classe minoritaire apparaît dans les <code>k</code> plus proches voisins, on doit réduire la valeur de <code>k</code> pour que la classe majoritaire ne domine pas.</p></li><li><p class="paragraph" style="text-align:left;">Si une classe minoritaire N&#39;apparaît PAS dans les <code>k</code> plus proches voisins, on ne modifiera probablement pas la valeur de <code>k</code> et on procédera à une classification plus globale.</p></li></ul><p class="paragraph" style="text-align:left;">Le seul inconvénient, c&#39;est que tu ne trouveras pas cette approche dans des implémentations open-source. D&#39;ailleurs, dans mes propres projets aussi, j&#39;ai dû écrire une implémentation custom, donc garde ça en tête.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi :</b> Quelles sont d&#39;autres façons de rendre les kNN plus robustes quand une classe a peu d&#39;échantillons ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=d83bf542-cd8a-4721-8bef-b9773098f474&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>L&#39;idée reçue sur apply() en Pandas</title>
  <description>🎯 Shot #318 - Cette méthode populaire n&#39;est qu&#39;une boucle for déguisée. Voici comment la remplacer.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b08e895d-bbff-44b8-a748-0ad1156287a7/_318_-_run-time_de_Pandas_apply.png.png" length="813991" type="image/png"/>
  <link>https://www.monshotdata.com/p/pandas-apply-methode-pas-vectorisee</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/pandas-apply-methode-pas-vectorisee</guid>
  <pubDate>Mon, 29 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-29T10:00:00Z</atom:published>
    <category><![CDATA[Pandas]]></category>
    <category><![CDATA[Shot Data]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">La méthode <code>apply()</code> de Pandas est l&#39;approche la plus courante pour appliquer une fonction le long d&#39;un axe d&#39;un DataFrame/Series.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fa5fa3b5-262e-4f80-be6f-a4e882120132/_318_-_Me%CC%81thode_apply.png.png?t=1782596413"/></div><p class="paragraph" style="text-align:left;">D&#39;après mon expérience, la plupart des utilisateurs de Pandas sont convaincus qu&#39;<code>apply()</code> est une méthode vectorisée.</p><p class="paragraph" style="text-align:left;">Autrement dit, ils pensent qu&#39;<code>apply()</code> opère efficacement, élément par élément, comme les autres opérations vectorisées de Pandas.</p><p class="paragraph" style="text-align:left;"><b>Mais c&#39;est FAUX.</b></p><p class="paragraph" style="text-align:left;">Contrairement à cette croyance répandue, <b>chaque utilisateur de Pandas DOIT savoir que la méthode </b><code>apply()</code><b> n&#39;est PAS vectorisée</b>.</p><p class="paragraph" style="text-align:left;">En réalité, c&#39;est simplement une boucle for Python déguisée, qui n&#39;offre aucune des optimisations liées à la vectorisation auxquelles on pourrait s&#39;attendre.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b7d75548-7cbb-4475-af4b-bccff7a9be7e/_318_-_e%CC%81quivalence_apply.png.png?t=1782596395"/></div><p class="paragraph" style="text-align:left;">Résultat : le code s&#39;exécute toujours à la vitesse native de Python. Autrement dit, lentement.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="quelles-sont-les-solutions">Quelles sont les solutions ?</h2><p class="paragraph" style="text-align:left;">Une solution consiste à éliminer la méthode <code>apply()</code> en utilisant une approche vectorisée à la place.</p><p class="paragraph" style="text-align:left;">Mais je comprends que parfois, trouver une approche vectorisée n&#39;est pas simple.</p><p class="paragraph" style="text-align:left;">Une autre solution que je trouve pratique est de paralléliser la méthode <code>apply()</code> en utilisant des bibliothèques tierces optimisées.</p><p class="paragraph" style="text-align:left;">L&#39;image ci-dessous compare le run-time de Pandas <code>apply()</code> avec quatre alternatives qui supportent la parallélisation :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b08e895d-bbff-44b8-a748-0ad1156287a7/_318_-_run-time_de_Pandas_apply.png.png?t=1782596445"/></div><p class="paragraph" style="text-align:left;">Il est évident que la méthode <code>apply()</code> de Pandas n&#39;est pas la façon optimale d&#39;appliquer une fonction. C&#39;est même la plus lente des cinq.</p><p class="paragraph" style="text-align:left;">Il y a deux raisons à cela :</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b>Pandas s&#39;exécute TOUJOURS sur un seul cœur du CPU</b>. Il ne possède donc aucune capacité de parallélisation qu&#39;il pourrait exploiter.</p></li></ol><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2c9f4001-1f5a-43f1-98d5-3fc4d441764e/_318_-_Pandas_s_exe%CC%81cute_TOUJOURS_sur_un_seul_c%C5%93ur_du_CPU.png.png?t=1782596493"/></div><ol start="2"><li><p class="paragraph" style="text-align:left;"><b>La méthode </b><code>apply()</code><b> de Pandas n&#39;est pas vectorisée</b>. Elle ne possède donc aucune capacité de vectorisation non plus.</p></li></ol><p class="paragraph" style="text-align:left;">Honnêtement, si les quatre bibliothèques externes présentées dans le visuel ci-dessus ne possèdent pas non plus de capacités de vectorisation, elles exploitent en revanche la parallélisation.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fb1521a1-0072-4fd4-b156-b90030a07777/_318_-_La_me%CC%81thode_apply___de_Pandas_n_est_pas_vectorise%CC%81e.png.png?t=1782596528"/></div><p class="paragraph" style="text-align:left;">C&#39;est comme ça qu&#39;on observe une amélioration massive du run-time en les utilisant.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Note bien ici que même si <code>mapply()</code> est la plus rapide dans cet exemple, cela ne signifie pas qu&#39;elle le sera toujours. Pense à faire un benchmark sur ton propre dataset d&#39;abord.</p><p class="paragraph" style="text-align:left;">De plus, je sais que la méthode <code>add_row()</code> que j&#39;ai utilisée dans l&#39;image ci-dessus peut facilement être vectorisée. J&#39;ai choisi cet exemple particulier uniquement par souci de simplicité.</p><p class="paragraph" style="text-align:left;">En guise de mot de la fin, retiens que <b>ta première tentative doit TOUJOURS être d&#39;écrire des opérations vectorisées</b>.</p><p class="paragraph" style="text-align:left;">N&#39;envisage ces bibliothèques tierces que lorsque tu ne vois aucune possibilité d&#39;écrire du code vectorisé, et que tu n&#39;as pas d&#39;autre choix que d&#39;utiliser <code>apply()</code>.</p><p class="paragraph" style="text-align:left;">Pour démarrer avec ces bibliothèques :</p><ul><li><p class="paragraph" style="text-align:left;">Swifter : <a class="link" href="https://github.com/jmcarpenter2/swifter?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=l-idee-recue-sur-apply-en-pandas" target="_blank" rel="noopener noreferrer nofollow">https://github.com/jmcarpenter2/swifter</a></p></li><li><p class="paragraph" style="text-align:left;">Pandarallel : <a class="link" href="https://github.com/nalepae/pandarallel?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=l-idee-recue-sur-apply-en-pandas" target="_blank" rel="noopener noreferrer nofollow">https://github.com/nalepae/pandarallel</a></p></li><li><p class="paragraph" style="text-align:left;">Parallel Pandas : <a class="link" href="https://pypi.org/project/parallel-pandas/?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=l-idee-recue-sur-apply-en-pandas" target="_blank" rel="noopener noreferrer nofollow">https://pypi.org/project/parallel-pandas/</a></p></li><li><p class="paragraph" style="text-align:left;">Mapply : <a class="link" href="https://pypi.org/project/mapply/?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=l-idee-recue-sur-apply-en-pandas" target="_blank" rel="noopener noreferrer nofollow">https://pypi.org/project/mapply/</a></p></li></ul><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi :</b> Quelles autres techniques utilises-tu couramment pour optimiser les opérations Pandas ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=d4c9eee8-cf08-451e-8f29-678143fabd07&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>NOT IN en SQL : l&#39;erreur invisible qui te coûte des heures</title>
  <description>🎯 Shot #317 - Comprendre le piège des valeurs NULL et 2 façons de l&#39;éviter.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4564e7b5-ed80-42d1-81d5-8a9eb42e88a5/_317_-_Code5.png.png" length="631703" type="image/png"/>
  <link>https://www.monshotdata.com/p/erreur-silencieuse-sql-not-in-null</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/erreur-silencieuse-sql-not-in-null</guid>
  <pubDate>Fri, 26 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-26T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Sql]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">D&#39;expérience, beaucoup d&#39;erreurs inattendues dans les bibliothèques, outils et langages sont liées à la présence de valeurs manquantes.</p><p class="paragraph" style="text-align:left;">Par exemple, considère un array NumPy 1D contenant des valeurs NaN.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c2f722f3-50f5-4347-9f75-05d01bc8d7e8/_317_-_Code1.png?t=1782289893"/></div><p class="paragraph" style="text-align:left;">Quand on agrège cet array NumPy pour calculer, disons, sa somme, on obtient le résultat suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/06ca114b-d985-4914-ab5a-6934891eec66/_317_-_Code2.png?t=1782289912"/></div><p class="paragraph" style="text-align:left;">Étrange, non ?</p><p class="paragraph" style="text-align:left;">Alors qu&#39;un résultat de 6 aurait eu plus de sens ici, NumPy produit une valeur <code>NaN</code> à la place.</p><p class="paragraph" style="text-align:left;">Bref, ce n&#39;est pas le sujet du jour, mais tu vois l&#39;idée.</p><p class="paragraph" style="text-align:left;">Une erreur silencieuse similaire existe aussi en SQL, plus précisément dans l&#39;utilisation de la clause <code>NOT IN</code>, et beaucoup d&#39;utilisateurs SQL ne la connaissent pas.</p><p class="paragraph" style="text-align:left;">Voyons ça !</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Imaginons qu&#39;on a les tables suivantes (<code>students</code> et <code>names</code>) dans notre base de données :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6a285aa4-80d1-4900-a449-55f807f20705/_317_-_Tables_students_et_names.png.png?t=1782290041"/></div><p class="paragraph" style="text-align:left;">L&#39;objectif est de sélectionner les enregistrements de la table <code>students</code> où <code>first_name</code> <b>n&#39;est pas</b> dans la table <code>names</code>.</p><p class="paragraph" style="text-align:left;">Une façon de faire est d&#39;utiliser la clause <code>NOT IN</code>, comme ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b3f992eb-542a-4c65-b05c-9710a74ff7f3/_317_-_Code3.png.png?t=1782290023"/></div><p class="paragraph" style="text-align:left;">Et on obtient bien les résultats attendus.</p><p class="paragraph" style="text-align:left;">Tout va bien jusque-là !</p><p class="paragraph" style="text-align:left;">Maintenant, supposons que notre table <code>names</code> contienne une valeur <code>NULL</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/53e58b89-6d77-4318-ba59-4894a87f031c/_317_-_Ajout_valeur_NULL.png.png?t=1782290064"/></div><p class="paragraph" style="text-align:left;">Si on relance la même requête, on n&#39;obtient aucun résultat cette fois :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ecf9836-1008-4ec3-8e4d-0144b8fe3e61/_317_-_Code4.png.png?t=1782290112"/></div><p class="paragraph" style="text-align:left;">Petite parenthèse : si on avait utilisé la clause <code>IN</code> pour sélectionner les lignes de la table <code>students</code> où <code>first_name</code> est <b>dans</b> la table <code>names</code>, on constate que ça fonctionne comme prévu :</p><p class="paragraph" style="text-align:left;"></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4564e7b5-ed80-42d1-81d5-8a9eb42e88a5/_317_-_Code5.png.png?t=1782290143"/></div><p class="paragraph" style="text-align:left;">image</p><p class="paragraph" style="text-align:left;">C&#39;est étrange, non ?</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="pourquoi-nobtienton-aucun-rsultat-a">Pourquoi n&#39;obtient-on aucun résultat avec NOT IN ?</h2><p class="paragraph" style="text-align:left;">La raison pour laquelle <code>NOT IN</code> ne retourne aucun résultat alors que <code>IN</code> fonctionne comme prévu tient au fonctionnement interne de ces deux clauses.</p><p class="paragraph" style="text-align:left;">Pour simplifier, imaginons qu&#39;on vérifie le premier enregistrement (où <code>first_name</code> est &quot;John&quot;) de la table <code>students</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2127530d-2093-49c8-a67f-e39bf025d3ff/_317_-_Chercher_dans.png?t=1782290174"/></div><p class="paragraph" style="text-align:left;">La clause <code>WHERE</code> a besoin d&#39;une valeur booléenne pour déterminer si un enregistrement doit être retenu ou non.</p><p class="paragraph" style="text-align:left;">Quand on utilise <code>IN</code>, cette valeur booléenne est évaluée avec l&#39;opérateur <code>OR</code> comme suit :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ea726cf-115f-471e-8b56-b6fe5cc3912c/_317_-_Code6.png?t=1782290216"/></div><p class="paragraph" style="text-align:left;">Si n&#39;importe quelle condition est <code>TRUE</code>, la ligne est retenue.</p><p class="paragraph" style="text-align:left;">En revanche, quand on utilise <code>NOT IN</code>, la valeur booléenne est évaluée avec l&#39;opérateur <code>AND</code> comme suit :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7793f5b6-6d3a-4410-a537-5d20bfdebf54/_317_-_Code7.png?t=1782290239"/></div><p class="paragraph" style="text-align:left;">Pour que cette expression soit <code>TRUE</code>, toutes les conditions individuelles DOIVENT être <code>TRUE</code>.</p><p class="paragraph" style="text-align:left;">Mais la condition (<code>JOHN != None</code>) pose problème car, en règle générale, elle produit une valeur <code>UNKNOWN</code>.</p><p class="paragraph" style="text-align:left;">L&#39;expression entière s&#39;évalue donc à <code>UNKNOWN</code>, et aucun enregistrement n&#39;est retourné.</p><p class="paragraph" style="text-align:left;">C&#39;est le cas pour chaque enregistrement de la table <code>students</code>. Résultat : la requête ne retourne aucun enregistrement :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ecf9836-1008-4ec3-8e4d-0144b8fe3e61/_317_-_Code4.png.png?t=1782290112"/></div><hr class="content_break"><h2 class="heading" style="text-align:left;" id="que-faire-la-place">Que faire à la place ?</h2><p class="paragraph" style="text-align:left;">Il existe plusieurs façons d&#39;éviter ça.</p><p class="paragraph" style="text-align:left;">Puisque notre objectif est de sélectionner les enregistrements de la table <code>students</code> où <code>first_name</code> n&#39;est pas dans la table <code>names</code>, on peut :</p><ul><li><p class="paragraph" style="text-align:left;"><b>Filtrer les valeurs NULL dans la sous-requête :</b></p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/10eebb8f-541f-4f02-84dc-0a72ed729d15/_317_-_Code8.png.png?t=1782290267"/></div><ul><li><p class="paragraph" style="text-align:left;"><b>Utiliser un Anti Join :</b> un anti join retourne uniquement les lignes de la table de gauche qui n&#39;ont aucune correspondance dans la table de droite. C&#39;est exactement ce qu&#39;il nous faut ici, et voici comment l&#39;implémenter :</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/81084539-b249-4a26-9ff6-ea79cab01a32/_317_-_Code9.png.png?t=1782290345"/></div><p class="paragraph" style="text-align:left;">Ce genre d&#39;erreurs peut parfois prendre un temps considérable à débugger si tu n&#39;en as pas conscience au préalable.</p><p class="paragraph" style="text-align:left;">J&#39;espère que ça t&#39;a été utile !</p><p class="paragraph" style="text-align:left;">Si tu veux expérimenter avec ce qu&#39;on a vu sur la clause <code>NOT IN</code> aujourd&#39;hui, télécharge ce Jupyter Notebook : <a class="link" href="https://docs.moncoachdata.com/w/cpnIusN?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=not-in-en-sql-l-erreur-invisible-qui-te-coute-des-heures" target="_blank" rel="noopener noreferrer nofollow">Notebook Clause NOT IN</a>.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi :</b> peux-tu proposer une autre solution au problème ci-dessus ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=608d5d93-859a-4d50-b322-4b3e612ac720&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Quantization : faire tourner des modèles ML géants sur du hardware minuscule</title>
  <description>👀​ Mini-cours #34 - Des formules affine et symétrique aux techniques de pointe pour LLM (LLM.int8, SmoothQuant), le guide complet pour compresser tes modèles sans sacrifier la précision.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/624a7ee3-cdd4-468a-9e0b-985928011d8b/mini-cours__34_-_cover_Quantization.png" length="87273" type="image/png"/>
  <link>https://www.monshotdata.com/p/quantization-machine-learning</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/quantization-machine-learning</guid>
  <pubDate>Wed, 24 Jun 2026 09:30:00 +0000</pubDate>
  <atom:published>2026-06-24T09:30:00Z</atom:published>
    <category><![CDATA[Déployer &amp; Optimiser Comme Un Pro]]></category>
    <category><![CDATA[Machine Learning]]></category>
    <category><![CDATA[Pro]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#f2eafe;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:2.0px 2.0px 2.0px 2.0px;"><p class="paragraph" style="text-align:left;"><span style="text-decoration:underline;"><b>Psst... Contenu Exclusif Réservé aux Membres !</b></span><br><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Ce mini-cours fait partie de notre espace premium. Rejoins dès maintenant le </span><b>Cercle des Experts</b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;"> pour débloquer l’intégralité de nos ressources, analyses approfondies et guides pratiques.</span><br><b>👉 </b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Clique ici pour découvrir les avantages et t’inscrire : </span><b><a class="link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule" target="_blank" rel="noopener noreferrer nofollow" style="color: #2563eb">Page d’adhésion</a></b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">.</span></p></div><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#222222;font-family:Poppins, Helvetica, sans-serif, serif, EmojiFont;font-size:16px;">⏱️ </span><i><b>Temps de lecture</b></i><i> : 30-40 minutes</i></p></div><p class="paragraph" style="text-align:left;">Dans un précédent deep dive consacré à la compression de modèles, nous avons passé en revue différentes façons de compresser un modèle ML une fois qu&#39;il est entraîné.</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/compression-modeles-machine-learning-efficace?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule" target="_blank"><div class="embed__content"><p class="embed__title"> Compression de modèles : un levier clé pour un machine learning efficace </p><p class="embed__description"> Apprends les techniques essentielles de compression de modèles ML : pruning, factorisation et quantification pour réduire l&#39;empreinte et accélérer l&#39;inférence. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/8ad2d417-5311-48af-b2a2-b758b9b58bc9/Mini-cours__17_-_Compression_de_mode%CC%80les_en_ML.png?t=1772986037"/></a></div><ul><li><p class="paragraph" style="text-align:left;">Tu as peut-être entraîné un modèle, mais il est trop gros pour être déployé. Les techniques de compression t&#39;aident à régler ça.</p></li><li><p class="paragraph" style="text-align:left;">Ou alors, tu veux utiliser un modèle open-source sur ta machine locale, et il est trop volumineux pour tenir en mémoire.</p></li></ul><p class="paragraph" style="text-align:left;">Dans ce deep dive là, nous avons vu plusieurs techniques qui permettent de réduire l&#39;empreinte mémoire des modèles ML et de les rendre plus accessibles et plus déployables.</p><p class="paragraph" style="text-align:left;">L&#39;une de ces techniques était la <b>quantization</b>. Nous l&#39;avions abordée avec un certain niveau de détail, mais pas avec toute la précision que ce sujet mérite vraiment pour un ingénieur ML.</p><p class="paragraph" style="text-align:left;">Dans ce dossier, on plonge donc dans les détails techniques de la quantization : ce que c&#39;est, comment ça marche, et pourquoi c&#39;est l&#39;une des techniques les plus puissantes pour exploiter de gros modèles sur des machines ordinaires.</p><div class="section" style="background-color:#f1e8fb;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:10.0px 10.0px 10.0px 10.0px;"><p class="paragraph" style="text-align:left;">👉 En tant qu&#39;ingénieur ML, savoir manier les techniques qui font économiser de l&#39;argent à ton employeur est sincèrement apprécié. Maîtriser la quantization, la compression de modèles, l&#39;optimisation, etc., te place clairement sur la voie pour devenir un atout indispensable dans ton équipe.</p></div><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><h2 class="heading" style="text-align:left;" id="motivation">Motivation</h2><p class="paragraph" style="text-align:left;">En règle générale, les paramètres d&#39;un réseau de neurones (les poids des couches) sont représentés avec des nombres à virgule flottante sur 32 bits.</p><p class="paragraph" style="text-align:left;">Le raisonnement est le suivant : comme les paramètres d&#39;un modèle ML ne sont contraints à aucune plage de valeurs précise, assigner un type de données capable de couvrir une large plage est une décision prudente. Ça évite l&#39;instabilité numérique et maintient une haute précision pendant l&#39;entraînement comme à l&#39;inférence.</p><p class="paragraph" style="text-align:left;">Évidemment, le gros inconvénient de cette approche, c&#39;est qu&#39;utiliser le plus grand type de données signifie aussi que le modèle consomme plus de mémoire.</p><p class="paragraph" style="text-align:left;">Imagine qu&#39;on puisse représenter ces mêmes paramètres avec des formats plus compacts : 16 bits, 8 bits, 4 bits, voire 1 bit, tout en préservant l&#39;essentiel de l&#39;information.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/ee968647-b52b-4671-89fe-1fd53bf71a31/Mini-cours__34_-_Quantization.png.png?t=1782244668"/></div><p class="paragraph" style="text-align:left;">Plutôt cool, non ?</p><p class="paragraph" style="text-align:left;">Ça réduirait drastiquement la quantité de mémoire nécessaire pour stocker les paramètres du modèle, sans compromettre significativement sa précision.</p><p class="paragraph" style="text-align:left;">C&#39;est exactement ce que permettent les techniques de quantization.</p><p class="paragraph" style="text-align:left;">Dans ce dossier, on va comprendre en détail pourquoi la quantization est nécessaire et à quel moment il vaut mieux quantizer le modèle, puis explorer les différents types de données et les méthodes de quantization modernes.</p><h3 class="heading" style="text-align:left;" id="questce-que-la-quantization">Qu&#39;est-ce que la quantization ?</h3><p class="paragraph" style="text-align:left;">Formellement, la quantization est le processus qui consiste à convertir des valeurs depuis une représentation riche en information (généralement un ensemble continu) vers une représentation plus compacte (généralement un ensemble discret).</p><p class="paragraph" style="text-align:left;">Un bon exemple de quantization, c&#39;est l&#39;échantillonnage d&#39;un signal analogique : chaque valeur d&#39;un signal continu se voit assigner une valeur tirée d&#39;un ensemble discret prédéfini.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4950dad4-7dd1-4c4a-925d-f5a9c01441b7/Mini-cours__34_-_Exemple_de_quantization.png.png?t=1782244653"/></div><p class="paragraph" style="text-align:left;">Dans le contexte des réseaux de neurones, la quantization consiste à convertir la précision des nombres (principalement les paramètres) utilisés dans notre modèle, en passant d&#39;une haute précision (comme un float 32 bits) à une précision plus basse (comme un entier 4 bits).</p><h3 class="heading" style="text-align:left;" id="pourquoi-quantizer">Pourquoi quantizer ?</h3><p class="paragraph" style="text-align:left;">La raison est assez évidente.</p><p class="paragraph" style="text-align:left;">Ça économise de la mémoire, ce qui, à son tour, économise de l&#39;argent.</p><p class="paragraph" style="text-align:left;">Pour te donner un ordre de grandeur, prends un modèle ML avec plus d&#39;un million de paramètres, chacun représenté par un float 32 bits.</p><p class="paragraph" style="text-align:left;">Si on peut les représenter avec des nombres sur 8 bits, on obtient une baisse significative de l&#39;usage mémoire (environ 75 %), tout en conservant la capacité de représenter une large plage de valeurs.</p><p class="paragraph" style="text-align:left;">De plus, les modèles quantizés nécessitent moins de ressources de calcul et sont plus rapides. Résultat : ils font économiser de l&#39;argent et améliorent l&#39;expérience utilisateur.</p><p class="paragraph" style="text-align:left;">Enfin, tout le monde n&#39;a pas accès à de gros clusters de GPU pour faire tourner d&#39;énormes modèles ML. Avec la quantization, les chercheurs et passionnés sans cluster GPU personnel peuvent expérimenter facilement avec de gros modèles modernes. Autrement dit, on peut exécuter efficacement des calculs directement sur les appareils des utilisateurs.</p><p class="paragraph" style="text-align:left;">Bien sûr, la quantization introduit un compromis entre efficacité (taille du modèle) et précision (accuracy). En réduisant la précision numérique, les prédictions du modèle deviennent plus approximatives que celles du modèle original en pleine précision.</p><hr class="content_break"><h3 class="heading" style="text-align:left;" id="quantization-vs-entranement-en-prci">Quantization vs entraînement en précision mixte</h3><p class="paragraph" style="text-align:left;">L&#39;entraînement en précision mixte (mixed precision training) est une technique similaire qui repose elle aussi sur l&#39;usage de plusieurs types de données.</p><p class="paragraph" style="text-align:left;">Quantization et précision mixte servent toutes deux à optimiser l&#39;efficacité computationnelle des modèles ML, mais elles s&#39;attaquent à des aspects différents, avec des approches d&#39;implémentation et des compromis distincts.</p><p class="paragraph" style="text-align:left;">Avant de passer aux techniques de quantization, il est donc important de bien comprendre ce qui les sépare.</p><p class="paragraph" style="text-align:left;"><b>Quantization</b></p><p class="paragraph" style="text-align:left;">Comme on l&#39;a vu plus haut, la quantization consiste à réduire la précision des poids et des activations, en passant de formats haute précision (comme le float 32 bits) à des formats basse précision (comme les entiers 16 ou 8 bits).</p><p class="paragraph" style="text-align:left;">Son objectif premier est de rendre les modèles plus petits et plus rapides <b>à l&#39;inférence</b>, ce qui est particulièrement utile pour déployer des modèles sur des appareils aux ressources limitées.</p><p class="paragraph" style="text-align:left;"><b>Entraînement en précision mixte</b></p><p class="paragraph" style="text-align:left;">L&#39;entraînement en précision mixte, lui, vise à accélérer le <b>processus d&#39;entraînement</b> en utilisant à la fois de l&#39;arithmétique haute précision (float 32 bits) et basse précision (float 16 bits) au sein du même modèle.</p><p class="paragraph" style="text-align:left;">On a déjà couvert ce sujet dans ce shot data ci-dessous : </p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/mixed-precision-training-pytorch?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule" target="_blank"><div class="embed__content"><p class="embed__title"> Mixed Precision Training avec PyTorch — Guide pratique </p><p class="embed__description"> Entraîne tes modèles deep learning 2,5× plus vite avec la mix précision training. Réduis la mémoire, augmente la vitesse sans sacrifier la précision. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/a98bd178-aa8a-444c-a5c5-4f1d56d024a1/_304_-_Les_e%CC%81tapes_a%CC%80_suivre_pour_exploiter_ces_acce%CC%81le%CC%81rations.gif?t=1777152931"/></a></div><p class="paragraph" style="text-align:left;">…mais faisons un rapide rappel de son fonctionnement.</p><hr class="content_break"><h4 class="heading" style="text-align:left;" id="comment-fonctionne-lentranement-en-">Comment fonctionne l&#39;entraînement en précision mixte ?</h4><p class="paragraph" style="text-align:left;">Les bibliothèques de deep learning classiques sont très conservatrices dans l&#39;attribution des types de données.</p><p class="paragraph" style="text-align:left;">Par défaut, le type assigné est souvent du 64 bits ou du 32 bits, alors qu&#39;il y aurait par exemple de la marge pour du 16 bits. C&#39;est ce qu&#39;illustre le code ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/36582b96-7dfa-4553-9e60-a0ab5d7f9fdc/_304_-_PyTorch_assigne_un_type_de_donne%CC%81es_gourmand_en_me%CC%81moire.png.png?t=1777063216"/></div><p class="paragraph" style="text-align:left;">Résultat : on n&#39;est pas du tout optimal dans l&#39;allocation mémoire.</p><p class="paragraph" style="text-align:left;">Bien sûr, ce choix vise à garantir une meilleure précision dans la représentation de l&#39;information.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1c11055b-eab0-40cf-be06-9429606351e2/_304_-_Allocations_me%CC%81moires.png.png?t=1777063216"/></div><p class="paragraph" style="text-align:left;">Mais cette précision a toujours un coût : une consommation mémoire supplémentaire, pas toujours souhaitable selon les situations.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6d243cfb-aefd-4551-8315-4976ad297ba9/_304_-_Consommation_me%CC%81moire_par_type_de_donne%CC%81es.png?t=1777063216"/></div><p class="paragraph" style="text-align:left;">On observe d&#39;ailleurs que beaucoup d&#39;opérations sur les tenseurs, en particulier la multiplication matricielle, sont bien plus rapides avec des types de données de plus faible précision, comme le montre l&#39;exemple ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/00bce325-83f6-45ee-a5af-9cf54123c743/_304_-_Ope%CC%81rations_tensorielles.png?t=1777063216"/></div><p class="paragraph" style="text-align:left;">Par ailleurs, comme le <code>float16</code> ne fait que la moitié de la taille du <code>float32</code>, son usage réduit la mémoire nécessaire pour entraîner le réseau.</p><p class="paragraph" style="text-align:left;">Ça permet aussi d&#39;entraîner de plus gros modèles, ou de travailler sur des mini-batches plus grands (ce qui accélère encore davantage l&#39;entraînement), etc.</p><p class="paragraph" style="text-align:left;"><b>L&#39;entraînement en précision mixte</b> est une technique fiable et <b>largement adoptée</b> dans l&#39;industrie pour atteindre cet objectif.</p><p class="paragraph" style="text-align:left;">Comme son nom l&#39;indique, l&#39;idée est d&#39;employer du <code>float16</code> basse précision (partout où c&#39;est faisable, comme dans les convolutions et les multiplications matricielles) en complément du <code>float32</code>. D&#39;où le nom de « précision mixte ».</p><p class="paragraph" style="text-align:left;">Voici une liste de quelques modèles que j&#39;ai trouvés et qui ont été entraînés en précision mixte :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/324e754d-d025-45ac-8b1d-54aeb35b73ba/_304_-_Liste_de_mode%CC%80les_entrai%CC%82ne%CC%81s_avec_le_mixed_precision_training.png?t=1777063216"/></div><p class="paragraph" style="text-align:left;">On voit clairement que la précision mixte est bien plus utilisée qu&#39;on ne le croit, même si on en entend rarement parler.</p><p class="paragraph" style="text-align:left;">Si tu veux entrer dans le détail technique et l&#39;implémentation, jette un œil à cette newsletter :</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/mixed-precision-training-pytorch?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule" target="_blank"><div class="embed__content"><p class="embed__title"> Mixed Precision Training avec PyTorch — Guide pratique </p><p class="embed__description"> Entraîne tes modèles deep learning 2.5× plus vite avec la mix précision training. Réduis la mémoire, augmente la vitesse sans sacrifier la précision. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/a98bd178-aa8a-444c-a5c5-4f1d56d024a1/_304_-_Les_e%CC%81tapes_a%CC%80_suivre_pour_exploiter_ces_acce%CC%81le%CC%81rations.gif?t=1777152931"/></a></div><hr class="content_break"><p class="paragraph" style="text-align:left;">Pour bien marquer la différence une dernière fois :</p><ul><li><p class="paragraph" style="text-align:left;">La <b>quantization</b> se concentre avant tout sur l&#39;optimisation de l&#39;inférence : rendre les modèles plus petits et plus rapides pour le déploiement (même s&#39;il existe aussi des façons de l&#39;utiliser pendant l&#39;entraînement).</p></li><li><p class="paragraph" style="text-align:left;">L&#39;<b>entraînement en précision mixte</b> sert principalement pendant la phase d&#39;entraînement, pour l&#39;accélérer et réduire l&#39;usage mémoire.</p></li></ul><hr class="content_break"><div class="section" style="background-color:#1B3A6B;border-color:#F7931E;border-radius:8px;border-style:solid;border-width:3px;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;">💡<span style="color:#FFFFFF;"> En continuant, tu vas découvrir : </span></p><ul><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Les deux variantes de quantization linéaire (affine et symétrique), leurs formules complètes et quand choisir l&#39;une plutôt que l&#39;autre.</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Une démo pas à pas pour quantizer à la main un tenseur 32 bits en entiers 8 bits.</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Quoi quantizer exactement dans un modèle (poids, activations) et la différence entre quantization statique et dynamique.</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">La notion de granularité, et pourquoi tu n&#39;es PAS libre de choisir n&#39;importe quelle dimension pour quantizer.</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Trois techniques de pointe pour quantizer les LLM et dompter les outliers : LLM.int8 et SmoothQuant.</span></p></li></ul></div><div class="paywall"><hr class="paywall__break"/><div class="paywall__content"><h2 class="paywall__header"> La suite de ce mini-cours est réservée aux membres du Cercle des Experts. </h2><p class="paywall__description"> Tu as déjà le début. Pour accéder à l’explication complète et à tous les contenus avancés, rejoins le Cercle des Experts dès maintenant. </p><p class="paywall__links"><a class="paywall__upgrade_link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule">Rejoindre le Cercle des Experts</a> Translation missing: en.app.shared.conjuction.or <a class="paywall__login_link" href="https://www.monshotdata.com/login?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=quantization-faire-tourner-des-modeles-ml-geants-sur-du-hardware-minuscule">Sign In</a></p><div class="paywall__upsell"><div class="paywall__upsell_header"><h3> En devenant membre, tu débloques </h3></div><ul class="paywall__upsell_features"><li class="paywall__upsell_feature"> L’intégralité de ce mini-cours (sans coupure) </li><li class="paywall__upsell_feature"> Tous les mini-cours archivés et les ressources associées </li><li class="paywall__upsell_feature"> 1 nouveau mini-cours chaque semaine pour progresser en continu </li></ul></div></div></div></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=aff49a6c-fb4d-4f2d-9e82-c65fe21b1314&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Scope en Python : comprendre la règle LEGB en quelques minutes</title>
  <description>🎯 Shot #316 - Pourquoi tes variables ne sont pas toujours accessibles, et comment Python résout ça.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b1cc46f3-2969-4ec6-ad16-237e63def2d1/_316_-_Code5.png.png" length="456486" type="image/png"/>
  <link>https://www.monshotdata.com/p/scope-python-regle-legb</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/scope-python-regle-legb</guid>
  <pubDate>Mon, 22 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-22T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;"><a class="link" href="https://www.monshotdata.com/p/boucle-for-vs-list-comprehension-une-diff-rence-fondamentale?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=scope-en-python-comprendre-la-regle-legb-en-quelques-minutes" target="_blank" rel="noopener noreferrer nofollow">Dans un récent shot data</a>, on a abordé une différence fondamentale entre les boucles for et les list comprehensions en Python.</p><p class="paragraph" style="text-align:left;">Voici le visuel de ce post pour un rappel rapide : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/efaf84d3-5f28-4eb5-9afd-d7001efb2728/_316_-_Diffe%CC%81rence_fondamentale_entre_les_boucles_for_et_les_list_comprehensions_en_Python.png.png?t=1781903564"/></div><p class="paragraph" style="text-align:left;">En résumé :</p><ul><li><p class="paragraph" style="text-align:left;">Après l&#39;exécution d&#39;une boucle for, la variable de boucle reste accessible.</p></li><li><p class="paragraph" style="text-align:left;">Après l&#39;exécution d&#39;une list comprehension, la variable de boucle N&#39;EST PAS accessible.</p></li></ul><p class="paragraph" style="text-align:left;">Comme je l&#39;ai mentionné dans ce shot data, c&#39;est étroitement lié à la notion de <b>scope</b> en Python. </p><p class="paragraph" style="text-align:left;">Voyons ça aujourd&#39;hui.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="questce-que-le-scope-dune-variable-">Qu&#39;est-ce que le scope d&#39;une variable et pourquoi en a-t-on besoin ?</h2><p class="paragraph" style="text-align:left;">En termes simples, le scope d&#39;une variable désigne les zones de ton programme dans lesquelles une variable donnée est accessible.</p><p class="paragraph" style="text-align:left;">Ce concept n&#39;est pas propre à Python. Il s&#39;applique à la programmation en général.</p><p class="paragraph" style="text-align:left;">L&#39;objectif est de limiter l&#39;accès aux variables à des zones précises du code, afin d&#39;éviter qu&#39;elles soient modifiées depuis n&#39;importe quel endroit du programme.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1669ad0d-cbba-4c56-a46e-578f1ea9d38a/_316_-_ScopeA_ne_peut_pas_modifier_la_variable_b.png.png?t=1781903655"/></div><p class="paragraph" style="text-align:left;">Ainsi, quand tu accèdes à N&#39;IMPORTE QUELLE variable, c&#39;est le <b>scope</b> qui détermine entièrement comment les noms seront recherchés dans ton code.</p><p class="paragraph" style="text-align:left;">En Python, la résolution de scope se fait sur quatre niveaux.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/603df48b-f24e-48a8-9150-bb6bceafc88c/_316_-_Re%CC%81solution_de_scope.png.png?t=1781903695"/></div><p class="paragraph" style="text-align:left;">Chaque fois que tu accèdes à un nom en Python (nom de variable, nom de fonction, nom de classe, etc.), l&#39;interpréteur Python le recherche dans l&#39;ordre suivant :</p><ol start="1"><li><p class="paragraph" style="text-align:left;"><b>L</b>ocal</p></li><li><p class="paragraph" style="text-align:left;"><b>E</b>nclosing (englobant)</p></li><li><p class="paragraph" style="text-align:left;"><b>G</b>lobal</p></li><li><p class="paragraph" style="text-align:left;"><b>B</b>uilt-in</p></li></ol><p class="paragraph" style="text-align:left;">C&#39;est ce qu&#39;on appelle la <b>règle LEGB</b>.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="rsolution-de-scope-legb-en-python">Résolution de scope LEGB en Python</h2><p class="paragraph" style="text-align:left;">Voyons chacun de ces niveaux !</p><h3 class="heading" style="text-align:left;" id="1-scope-local">#1) Scope local</h3><p class="paragraph" style="text-align:left;">L&#39;exemple le plus simple de scope local, ce sont des variables déclarées à l&#39;intérieur d&#39;une fonction, comme illustré ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/704c6aa6-3ca5-4e79-bc92-485f15b90c57/_316_-_Code1.png.png?t=1781903885"/></div><p class="paragraph" style="text-align:left;">La variable <code>myVar</code> a un scope local dans <code>funcA</code>, ce qui signifie qu&#39;elle n&#39;est accessible qu&#39;à l&#39;intérieur de la fonction.</p><p class="paragraph" style="text-align:left;">Si tu essaies d&#39;accéder à <code>myVar</code> en dehors de <code>funcA</code>, tu obtiens, sans surprise, une erreur car la variable est locale à <code>funcA</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f640589c-3aa0-4649-8edd-bd3fe43a6d2b/_316_-_Code2.png.png?t=1781903922"/></div><p class="paragraph" style="text-align:left;">Ensuite, si tu as deux fonctions <b>non imbriquées</b>, tu remarqueras que les variables déclarées dans une fonction ne sont pas accessibles dans l&#39;autre :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9bbe7689-6cd1-4cbc-b5aa-bfc1c788a5c4/_316_-_Code3.png.png?t=1781903953"/></div><p class="paragraph" style="text-align:left;">C&#39;est le principe du scope local, et en Python, <b>il a la priorité la plus haute lors de la résolution de scope</b>.</p><p class="paragraph" style="text-align:left;">Autrement dit, si le même nom de variable existe à plusieurs endroits dans un programme, Python utilisera la variable qui se trouve dans le scope local depuis lequel elle a été accédée.</p><p class="paragraph" style="text-align:left;">Par exemple, dans le code ci-dessous, <code>myVar</code> est déclarée dans <code>funcA</code> et dans <code>funcB</code>. Quand on appelle <code>funcA()</code>, Python trouve <code>myVar</code> dans le scope local et l&#39;affiche :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/605b0527-57cd-4507-a255-8e25ba883ed8/_316_-_Code4.png.png?t=1781904007"/></div><p class="paragraph" style="text-align:left;">Si la variable est trouvée dans le scope local, parfait.</p><p class="paragraph" style="text-align:left;">Sinon, Python passe au <b>scope englobant</b> (s&#39;il existe) pour trouver la variable.</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><hr class="content_break"><h3 class="heading" style="text-align:left;" id="2-scope-englobant-enclosing">#2) Scope englobant (Enclosing)</h3><p class="paragraph" style="text-align:left;">En Python, le scope englobant apparaît quand tu as des <b>fonctions imbriquées</b>, c&#39;est-à-dire une ou plusieurs fonctions à l&#39;intérieur d&#39;une autre fonction.</p><p class="paragraph" style="text-align:left;">Par exemple, reprends le dernier code ci-dessus. Déclarons <code>funcB</code> à l&#39;intérieur de <code>funcA</code>.</p><p class="paragraph" style="text-align:left;">Le scope local et le scope englobant par rapport à <code>funcB</code> sont illustrés ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/b1cc46f3-2969-4ec6-ad16-237e63def2d1/_316_-_Code5.png.png?t=1781904053"/></div><p class="paragraph" style="text-align:left;">Considère maintenant le code suivant, où <code>myVar</code> n&#39;est pas disponible dans le scope local de <code>funcB</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/9defb229-aa63-4a43-94c7-4de826b899cb/_316_-_Code6.png.png?t=1781904097"/></div><p class="paragraph" style="text-align:left;">Comme le scope local ne contient pas de variable myVar, Python va d&#39;abord vérifier s&#39;il existe un scope englobant.</p><p class="paragraph" style="text-align:left;">Oui, il y en a un : funcA !</p><p class="paragraph" style="text-align:left;">Ensuite, il va vérifier si <code>myVar</code> est déclarée dans <code>funcA</code>.</p><p class="paragraph" style="text-align:left;">Bien sûr que oui !</p><p class="paragraph" style="text-align:left;">Python utilise la valeur déclarée dans le scope englobant pour <code>myVar</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7673ee5c-8963-4e6a-9d97-90c80b559f05/_316_-_Code7.png.png?t=1781904160"/></div><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><hr class="content_break"><h3 class="heading" style="text-align:left;" id="3-scope-global">#3) Scope global</h3><p class="paragraph" style="text-align:left;">Le scope global, comme tu l&#39;as probablement deviné, est le scope le plus large.</p><p class="paragraph" style="text-align:left;">Ici, <b>les variables et fonctions</b> sont déclarées en dehors de tout bloc, fonction ou classe spécifique.</p><p class="paragraph" style="text-align:left;">Elles sont donc accessibles (mais pas directement modifiables) depuis n&#39;importe quelle partie du programme, peu importe où elles sont définies.</p><p class="paragraph" style="text-align:left;">Par exemple, dans le code ci-dessous, ni <code>funcA</code> ni <code>funcB</code> n&#39;ont la variable <code>myVar</code> définie dans leur scope local respectif :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a0b3e259-20ca-44fb-88f4-8e5128e64eeb/_316_-_Code8.png.png?t=1781904217"/></div><p class="paragraph" style="text-align:left;">Il n&#39;y a pas non plus de scope englobant.</p><p class="paragraph" style="text-align:left;">Python vérifie donc si <code>myVar</code> est disponible dans le scope global, et elle l&#39;est effectivement.</p><p class="paragraph" style="text-align:left;">Ainsi, lors des <code>print</code>, on obtient la valeur globale de <code>myVar</code>, à savoir 10.</p><p class="paragraph" style="text-align:left;"><i>En guise d&#39;exercice, peux-tu dire quel sera l&#39;output dans ce cas :</i></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7083e6db-0e80-4ea1-8e09-4aedc52047a2/_316_-_Code9.png.png?t=1781904250"/></div><hr class="content_break"><h3 class="heading" style="text-align:left;" id="4-scope-builtin">#4) Scope built-in</h3><p class="paragraph" style="text-align:left;">Le dernier dans l&#39;ordre de priorité de la résolution de scope est le scope built-in.</p><p class="paragraph" style="text-align:left;">Ce sont des noms de variables qui sont automatiquement chargés dans le scope global de Python quand tu :</p><ul><li><p class="paragraph" style="text-align:left;">exécutes un script,</p></li><li><p class="paragraph" style="text-align:left;">ou ouvres une session Python interactive.</p></li></ul><p class="paragraph" style="text-align:left;">Ces variables built-in sont accessibles via le nom <code>__builtins__</code>, et il y en a plus de 150 : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/31c82b6c-d6b0-4a57-a7c2-1ea503e2137a/_316_-_Code10.png.png?t=1781904653"/></div><p class="paragraph" style="text-align:left;">Parmi les plus courants : <code>float</code>, <code>int</code>, <code>len</code>, <code>set</code>, <code>dict</code>, <code>range</code>, <code>str</code>, <code>zip</code>, et bien d&#39;autres.</p><p class="paragraph" style="text-align:left;">Si une variable n&#39;est pas trouvée dans le scope local, ni dans le scope englobant, ni même dans le scope global, Python tente de la trouver dans le scope built-in.</p><p class="paragraph" style="text-align:left;">Et c&#39;est ainsi que fonctionne la résolution de scope en Python.</p><hr class="content_break"><p id="retour-lexemple-list-comprehension-" class="paragraph" style="text-align:left;">Retour à l&#39;exemple : list comprehension vs. boucle for 👇</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/efaf84d3-5f28-4eb5-9afd-d7001efb2728/_316_-_Diffe%CC%81rence_fondamentale_entre_les_boucles_for_et_les_list_comprehensions_en_Python.png.png?t=1781903564"/></div><p class="paragraph" style="text-align:left;">La variable de boucle (<code>loop_var</code>) n&#39;est pas accessible après l&#39;exécution d&#39;une list comprehension parce qu&#39;elle est définie dans son scope local.</p><p class="paragraph" style="text-align:left;">En revanche, la variable de boucle est définie dans le scope global dans la boucle for du code ci-dessus. Elle reste donc accessible après l&#39;exécution de la boucle.</p><p class="paragraph" style="text-align:left;">J&#39;espère que tu as appris quelque chose de nouveau aujourd&#39;hui.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi de jouer :</b> sais-tu comment modifier une variable globale depuis le scope local d&#39;une fonction ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=005302d5-1afb-4379-b9ab-108b7042c807&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>DBSCAN++ : l&#39;alternative plus rapide et scalable à DBSCAN</title>
  <description>🎯 Shot #315 - Pourquoi DBSCAN est trop lent pour tes données, et comment DBSCAN++ résout le problème ?</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fb164fc3-c568-4d79-8df5-bb0bb60a6712/_315_-_DBSCAN_vs_DBSCAN%2B%2B.png.png" length="1026404" type="image/png"/>
  <link>https://www.monshotdata.com/p/dbscan-plus-plus-alternative-rapide-scalable</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/dbscan-plus-plus-alternative-rapide-scalable</guid>
  <pubDate>Fri, 19 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-19T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;"><b>Les algorithmes non paramétriques non supervisés sont largement utilisés en entreprise pour analyser de grands jeux de données.</b></p><p class="paragraph" style="text-align:left;">La raison est simple : dans beaucoup d&#39;applications concrètes, obtenir les vraies étiquettes (labels) est très difficile, voire impossible.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0c9021dc-3781-4499-83a2-065e1b09d4e4/_315_-_Me%CC%81thodes_non_parame%CC%81triques_non_supervise%CC%81es.png.png?t=1781861214"/></div><p class="paragraph" style="text-align:left;">Dans ces cas-là :</p><ul><li><p class="paragraph" style="text-align:left;">Soit les équipes data annotent les données, ce qui peut s&#39;avérer infaisable en pratique,</p></li><li><p class="paragraph" style="text-align:left;">Soit on utilise des méthodes non supervisées pour identifier des patterns.</p></li></ul><p class="paragraph" style="text-align:left;">Si KMeans est très répandu ici grâce à sa simplicité et son efficacité en tant qu&#39;algorithme de clustering, il a de nombreuses limites :</p><ul><li><p class="paragraph" style="text-align:left;">Il ne prend pas en compte la covariance des clusters.</p></li><li><p class="paragraph" style="text-align:left;">Il ne peut produire que des clusters sphériques. Comme tu peux le voir ci-dessous, même si les données forment des clusters non circulaires, il produit quand même des clusters ronds.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5af5ef30-dbce-4146-ad3f-684fee9b89f2/_315_-_Clustering_KMeans.png?t=1781861237"/></div><p class="paragraph" style="text-align:left;">Les algorithmes basés sur la densité, comme DBSCAN, répondent assez efficacement à ces limitations.</p><p class="paragraph" style="text-align:left;">L&#39;idée centrale derrière DBSCAN est de regrouper les points de données en fonction de la &quot;densité&quot;, c&#39;est-à-dire que les points proches les uns des autres dans une région de haute densité sont groupés ensemble, et séparés des autres par des régions de plus faible densité.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8829f2cd-c726-4715-84ad-8aa67b2a9942/_315_-_DBSCAN.png.png?t=1781861277"/></div><p class="paragraph" style="text-align:left;">Mais malheureusement, avec DBSCAN, on se heurte à un autre problème souvent sous-estimé.</p><p class="paragraph" style="text-align:left;">L&#39;un des éléments qui rend DBSCAN parfois inutilisable en pratique, c&#39;est son temps d&#39;exécution.</p><p class="paragraph" style="text-align:left;">Jusqu&#39;à récemment, on pensait que DBSCAN avait une complexité de <code>O(nlogn)</code>, mais il a été prouvé qu&#39;elle est de <code>O(n²)</code> dans le pire des cas.</p><p class="paragraph" style="text-align:left;">D&#39;ailleurs, on peut aussi le vérifier sur la figure ci-dessous. Elle montre le temps d&#39;exécution de DBSCAN en fonction du nombre d&#39;échantillons :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4a388409-f079-4064-8129-53ede4ab1884/_315_-_Temps_d_exe%CC%81cution_quadratique.png.png?t=1781861305"/></div><p class="paragraph" style="text-align:left;">C&#39;est clair : DBSCAN a une relation quadratique avec la taille du jeu de données.</p><p class="paragraph" style="text-align:left;">Il y a donc un besoin croissant de développer des versions plus efficaces de DBSCAN.</p><p class="paragraph" style="text-align:left;"><b>DBSCAN++ est un pas majeur vers un DBSCAN rapide et scalable.</b></p><p class="paragraph" style="text-align:left;">En résumé, DBSCAN++ repose sur l&#39;observation suivante : on n&#39;a besoin de calculer les estimations de densité que pour un sous-ensemble &quot;<code>m</code>&quot; des &quot;<code>n</code>&quot; points du jeu de données, où &quot;<code>m</code>&quot; peut être bien plus petit que &quot;<code>n</code>&quot; pour obtenir un clustering correct.</p><p class="paragraph" style="text-align:left;">L&#39;efficacité de DBSCAN++ est évidente sur l&#39;image ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fb164fc3-c568-4d79-8df5-bb0bb60a6712/_315_-_DBSCAN_vs_DBSCAN%2B%2B.png.png?t=1781861341"/></div><p class="paragraph" style="text-align:left;">Sur un jeu de données de 60 000 points :</p><ul><li><p class="paragraph" style="text-align:left;">DBSCAN++ est 20x plus rapide que DBSCAN.</p></li><li><p class="paragraph" style="text-align:left;">DBSCAN++ produit de meilleurs scores de clustering que DBSCAN.</p></li></ul><p class="paragraph" style="text-align:left;"><b>Mais comment ça fonctionne de bout en bout ?</b></p><ul><li><p class="paragraph" style="text-align:left;">Pourquoi sélectionner un sous-ensemble de points reste efficace ?</p></li><li><p class="paragraph" style="text-align:left;">Quelles stratégies peut-on utiliser pour sélectionner ce sous-ensemble ?</p></li><li><p class="paragraph" style="text-align:left;">Quelles autres limitations DBSCAN++ résout-il ?</p></li><li><p class="paragraph" style="text-align:left;">DBSCAN++ est un algorithme récent. Quels sont les points à garder en tête pour l&#39;utiliser efficacement ?</p></li></ul><p class="paragraph" style="text-align:left;">Si tu es curieux, le dernier deep dive en machine learning traite exactement de ce sujet : DBSCAN++ : <a class="link" href="https://www.monshotdata.com/p/dbscan-plus-plus-clustering-scalable?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=dbscan-l-alternative-plus-rapide-et-scalable-a-dbscan" target="_blank" rel="noopener noreferrer nofollow">l&#39;alternative plus rapide et scalable au clustering DBSCAN</a>.</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/dbscan-plus-plus-clustering-scalable?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=dbscan-l-alternative-plus-rapide-et-scalable-a-dbscan" target="_blank"><div class="embed__content"><p class="embed__title"> DBSCAN++ : Passe ton Clustering à l&#39;échelle supérieure </p><p class="embed__description"> Surmonte les limites de DBSCAN. Apprends comment DBSCAN++ et le K-center sampling offrent une alternative rapide et scalable pour tes grands jeux de données. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/98fbac48-c782-4ddd-8e10-c1a1a67a1fd6/Mini-cours__24_-_La_limite_du_clustering_DBSCAN.png.png?t=1774535041"/></a></div><p class="paragraph" style="text-align:left;">La plupart des jeux de données réels sont non supervisés et naturellement très volumineux :</p><ul><li><p class="paragraph" style="text-align:left;">KMeans n&#39;est généralement pas adapté à cause des hypothèses strictes mentionnées plus haut.</p></li><li><p class="paragraph" style="text-align:left;">DBSCAN peut fonctionner, mais il souffrira du temps d&#39;exécution.</p></li><li><p class="paragraph" style="text-align:left;">Du coup, connaître des algorithmes comme DBSCAN++ devient vraiment essentiel.</p></li></ul><p class="paragraph" style="text-align:left;">Bien sûr, je sais que beaucoup d&#39;entre vous n&#39;ont pas forcément une compréhension claire de DBSCAN lui-même.</p><p class="paragraph" style="text-align:left;">J&#39;ai donc aussi fourni une présentation détaillée de DBSCAN, qui sert de base naturelle pour comprendre DBSCAN++.</p><p class="paragraph" style="text-align:left;">Autre point : un problème avec DBSCAN++, c&#39;est qu&#39;il n&#39;est pas intégré dans Sklearn.</p><p class="paragraph" style="text-align:left;">Mais pas de panique.</p><p class="paragraph" style="text-align:left;">Pour cet article, j&#39;ai écrit une implémentation entièrement vectorisée de DBSCAN++, qui est liée dans l&#39;article et que tu peux utiliser dans tes projets.</p><p class="paragraph" style="text-align:left;">Lis le deep dive ici : <a class="link" href="https://www.monshotdata.com/p/dbscan-plus-plus-clustering-scalable?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=dbscan-l-alternative-plus-rapide-et-scalable-a-dbscan" target="_blank" rel="noopener noreferrer nofollow">DBSCAN++ : l&#39;alternative plus rapide et scalable au clustering DBSCAN</a>.</p><p class="paragraph" style="text-align:left;">Je suis convaincu qu&#39;apprendre DBSCAN++ sera extrêmement précieux pour tes compétences et tes projets futurs :)</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=7f1ffee2-a07d-4213-af0e-6e7faef64bee&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Booste tes modèles ML sans changer d&#39;algorithme (Partie 2)</title>
  <description>👀​ Mini-cours #33 - Data shuffling, encodage cyclique, focal loss, classification ordinale : Maîtrise les optimisations que les autres ignorent.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/464e530d-c4a0-467c-8c55-c25365617cbc/Mini-cours__33_-_Mini-batch_gradient_descent.png" length="89731" type="image/png"/>
  <link>https://www.monshotdata.com/p/techniques-ml-avancees-focal-loss-breathing-kmeans-features-cycliques</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/techniques-ml-avancees-focal-loss-breathing-kmeans-features-cycliques</guid>
  <pubDate>Wed, 10 Jun 2026 09:30:00 +0000</pubDate>
  <atom:published>2026-06-10T09:30:00Z</atom:published>
    <category><![CDATA[Machine Learning]]></category>
    <category><![CDATA[Qualité &amp; Architecture]]></category>
    <category><![CDATA[Pro]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#f2eafe;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:2.0px 2.0px 2.0px 2.0px;"><p class="paragraph" style="text-align:left;"><span style="text-decoration:underline;"><b>Psst... Contenu Exclusif Réservé aux Membres !</b></span><br><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Ce mini-cours fait partie de notre espace premium. Rejoins dès maintenant le </span><b>Cercle des Experts</b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;"> pour débloquer l’intégralité de nos ressources, analyses approfondies et guides pratiques.</span><br><b>👉 </b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Clique ici pour découvrir les avantages et t’inscrire : </span><b><a class="link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-2" target="_blank" rel="noopener noreferrer nofollow" style="color: #2563eb">Page d’adhésion</a></b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">.</span></p></div><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#222222;font-family:Poppins, Helvetica, sans-serif, serif, EmojiFont;font-size:16px;">⏱️ </span><i><b>Temps de lecture</b></i><i> : environ 30 minutes</i></p></div><p class="paragraph" style="text-align:left;">Dans la Partie 1, on a couvert 5 techniques puissantes : la régression de Huber, le kNN pondéré par la distance, la mise à jour dynamique de k, la discrétisation de features, et le label smoothing.</p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/techniques-ml-avancees-regression-huber-knn-label-smoothing?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-2" target="_blank"><div class="embed__content"><p class="embed__title"> Booste tes modèles ML sans changer d&#39;algorithme (Partie 1) </p><p class="embed__description"> Régression de Huber, kNN dynamique, discrétisation de features, label smoothing : 5 techniques ML concrètes avec code pour améliorer tes modèles sans les complexifier. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/6eb7f75d-c563-490c-96e9-6939757e60bd/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-3.png?t=1779916534"/></a></div><p class="paragraph" style="text-align:left;">Dans cette Partie 2, on plonge dans les 6 techniques restantes. Des sujets encore plus avancés, moins connus, et qui peuvent faire une vraie différence sur tes modèles en production.</p><p class="paragraph" style="text-align:left;">C&#39;est parti.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="technique-6-data-shuffling">Technique #6 : Data Shuffling</h2><h3 class="heading" style="text-align:left;" id="motivation">Motivation</h3><p class="paragraph" style="text-align:left;">Les modèles de deep learning peuvent échouer à converger pour de nombreuses raisons.</p><p class="paragraph" style="text-align:left;">Certaines causes sont évidentes et faciles à corriger : un learning rate trop élevé ou trop faible, l&#39;absence de normalisation des données, l&#39;absence de batch normalization, etc.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/eed3fd50-32cf-41f3-b8e7-eeea76344562/Mini-cours__33_-_E%CC%81chec_de_convergence.png?t=1781038690"/></div><p class="paragraph" style="text-align:left;">Le vrai problème, c&#39;est quand la cause n&#39;est pas évidente. Dans ce cas, le debugging peut prendre un temps considérable si tu n&#39;es pas au courant de certains pièges.</p><p class="paragraph" style="text-align:left;">Prenons un réseau de neurones de classification entraîné avec le mini-batch gradient descent :</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/464e530d-c4a0-467c-8c55-c25365617cbc/Mini-cours__33_-_Mini-batch_gradient_descent.png?t=1781038724"/></div><p class="paragraph" style="text-align:left;">On entraîne ici deux réseaux de neurones distincts :</p><ul><li><p class="paragraph" style="text-align:left;">Version 1 : le dataset est ordonné par labels.</p></li><li><p class="paragraph" style="text-align:left;">Version 2 : le dataset est correctement mélangé.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/668aa500-8e12-46b9-b5b0-005160f7c52a/Mini-cours__33_-_deux_re%CC%81seaux_de_neurones_distincts.png?t=1781038745"/></div><p class="paragraph" style="text-align:left;">Bien sûr, avant l&#39;entraînement, on s&#39;assure que les deux réseaux ont les mêmes poids initiaux, le même learning rate et les mêmes paramètres.</p><p class="paragraph" style="text-align:left;">Le graphique ci-dessous illustre les performances des deux modèles epoch par epoch. À gauche, le modèle entraîné sur les données ordonnées par label. À droite, le modèle entraîné sur les données mélangées.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f1c987ac-8d2c-478b-9ee8-3ff97ffd9557/Mini-cours__33_-_Performances_des_deux_mode%CC%80les_epoch_par_epoch.png.png?t=1781038792"/></div><p class="paragraph" style="text-align:left;">Le constat est sans appel : le modèle recevant les données ordonnées par label échoue complètement à converger, tandis que l&#39;autre converge sans problème.</p><h3 class="heading" style="text-align:left;" id="pourquoi-mlanger-les-donnes">Pourquoi mélanger les données ?</h3><p class="paragraph" style="text-align:left;">Si on y réfléchit, les deux modèles ont reçu exactement les mêmes données, non ?</p><p class="paragraph" style="text-align:left;">Pourtant, l&#39;ordre dans lequel ces données leur ont été présentées a totalement déterminé leurs performances.</p><p class="paragraph" style="text-align:left;">Je me souviens très bien d&#39;avoir rencontré ce problème. Je savais que mes données étaient ordonnées par labels. Mais l&#39;idée que cet ordre puisse influencer les performances du modèle ne m&#39;avait jamais traversé l&#39;esprit, puisque les données restent les mêmes quel que soit l&#39;ordre.</p><p class="paragraph" style="text-align:left;">J&#39;ai compris plus tard que ce raisonnement n&#39;est valable que lorsque le modèle voit toutes les données d&#39;un coup et met à jour ses poids en une seule fois, c&#39;est-à-dire en <b>batch gradient descent</b> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3c5875d4-33f2-4802-8581-c83d79da5750/Mini-cours__33_-_batch_gradient_descent.png?t=1781038854"/></div><p class="paragraph" style="text-align:left;">Mais en mini-batch gradient descent, les poids sont mis à jour après chaque mini-batch.</p><p class="paragraph" style="text-align:left;">Ainsi, la prédiction et la mise à jour des poids sur un mini-batch donné sont influencées par les mini-batchs précédents.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8be56554-677d-4607-8fb6-753983769648/Mini-cours__33_-_Influence_des_mini-batch_pre%CC%81ce%CC%81dents.png.png?t=1781038944"/></div><p class="paragraph" style="text-align:left;">Dans le contexte de données ordonnées par label, où les exemples d&#39;une même classe sont regroupés ensemble, le mini-batch gradient descent va pousser le modèle à apprendre des patterns spécifiques à la classe vue en majorité en début d&#39;entraînement.</p><p class="paragraph" style="text-align:left;">À l&#39;inverse, des données aléatoirement mélangées garantissent que chaque mini-batch contient une représentation équilibrée des classes. Le modèle apprend ainsi un ensemble de features plus complet tout au long de l&#39;entraînement.</p><div class="blockquote"><blockquote class="blockquote__quote"></blockquote></div><p class="paragraph" style="text-align:left;">La bonne nouvelle : si tu utilises le <code>DataLoader</code> de PyTorch, tu es protégé. Il implémente déjà le shuffling par défaut. Mais si tu as une implémentation personnalisée, vérifie que tu ne commets pas cette erreur.</p><p class="paragraph" style="text-align:left;">Avant de passer au point suivant, retiens ceci : les réseaux de neurones sont capables d&#39;apprendre des patterns totalement inexistants dans tes données. Ne leur en donne jamais l&#39;occasion.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="technique-7-rgression-zero-inflated">Technique #7 : Régression Zero-Inflated</h2><h3 class="heading" style="text-align:left;" id="motivation">Motivation</h3><p class="paragraph" style="text-align:left;">La variable cible d&#39;un dataset de régression classique suit généralement une distribution relativement équilibrée.</p><p class="paragraph" style="text-align:left;">Mais parfois, la variable cible contient un grand nombre de zéros. On appelle ces datasets des datasets zero-inflated.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/fc9899f2-e609-4a91-afd5-02f9dcdaf7ef/Mini-cours__33_-_datasets_zero-inflated.png?t=1781039020"/></div><p class="paragraph" style="text-align:left;">Ils posent des problèmes lors de la modélisation en régression, car un modèle de régression ne peut pas toujours prédire exactement &quot;zéro&quot; quand il le devrait.</p><p class="paragraph" style="text-align:left;">Prenons la régression linéaire simple. La droite de régression ne produira exactement &quot;zéro&quot; qu&#39;une seule fois (si sa pente est non nulle).</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2a8f6422-91e3-4bf0-984f-1b2fbd0031ff/Mini-cours__33_-_sortie_nulle_une_seule_fois.png?t=1781039104"/></div><p class="paragraph" style="text-align:left;">Ce problème persiste :</p><ul><li><p class="paragraph" style="text-align:left;">Dans les dimensions supérieures.</p></li><li><p class="paragraph" style="text-align:left;">Dans les modèles complexes comme les réseaux de neurones pour la régression.</p></li></ul><p class="paragraph" style="text-align:left;">Une excellente façon de résoudre ce problème consiste à combiner un modèle de classification et un modèle de régression. Voici comment :</p><ul><li><p class="paragraph" style="text-align:left;">Marque toutes les cibles non nulles comme &quot;1&quot; et les autres comme &quot;0&quot;.</p></li><li><p class="paragraph" style="text-align:left;">Entraîne un classifier binaire sur ce dataset.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/917df4d4-d0ce-46b9-bb27-3f2af1311256/Mini-cours__33_-_Entrai%CC%82ner_un_classifier_binaire_sur_ce_dataset.png?t=1781039219"/></div><ul><li><p class="paragraph" style="text-align:left;">Entraîne ensuite un modèle de régression uniquement sur les points de données avec <b>une cible non nulle</b>.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a24afca8-ff73-46bd-873d-610531c14ec8/Mini-cours__33_-_Entrai%CC%82ner_ensuite_un_mode%CC%80le_de_re%CC%81gression_uniquement_sur_les_points_de_donne%CC%81es_avec_une_cible_non_nulle.png?t=1781039233"/></div><p class="paragraph" style="text-align:left;">Lors de la prédiction :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7b336a56-aaf7-4131-9e72-a167abea5dab/Mini-cours__33_-_Pendant_la_pre%CC%81diction.png?t=1781039293"/></div><ul><li><p class="paragraph" style="text-align:left;">Si la sortie du classifier est 0, la prédiction finale est aussi zéro.</p></li><li><p class="paragraph" style="text-align:left;">Si la sortie du classifier est 1, on utilise le modèle de régression pour prédire la valeur finale.</p></li></ul><h3 class="heading" style="text-align:left;" id="exprience">Expérience</h3><p class="paragraph" style="text-align:left;">Pour cette expérience, considère le dataset fictif suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/60c05c83-78a4-421c-9539-aa192b1cefc6/Mini-cours__33_-_Donne%CC%81es_zero-inflated.png?t=1781039374"/></div><p class="paragraph" style="text-align:left;">Le code pour générer ce dataset est un peu long, mais il ne contient que quatre étapes simples :</p><ul><li><p class="paragraph" style="text-align:left;">Définir un tableau NumPy 2D avec des valeurs dans la 1ère colonne de [0, 100] et la 2ème colonne remplie de zéros.</p></li><li><p class="paragraph" style="text-align:left;">Définir un deuxième tableau NumPy 2D avec des valeurs dans la 1ère colonne de [300, 400] et la 2ème colonne remplie de zéros.</p></li><li><p class="paragraph" style="text-align:left;">Définir un troisième tableau NumPy 2D avec des valeurs dans la 1ère colonne de [100, 300] et la 2ème colonne linéairement dépendante de la 1ère colonne, avec du bruit aléatoire.</p></li><li><p class="paragraph" style="text-align:left;">Concaténer ces trois tableaux pour obtenir le dataset final, qu&#39;on appellera <code>data</code>.</p></li></ul><p class="paragraph" style="text-align:left;">En entraînant un modèle de régression linéaire sur ce dataset, on obtient le fit suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a94f082b-d7d8-4d4c-8090-be3270d18701/Mini-cours__33_-_Entrai%CC%82ner_un_mode%CC%80le_de_re%CC%81gression_line%CC%81aire_sur_ce_dataset.png?t=1781039436"/></div><p class="paragraph" style="text-align:left;">Il est clair que la régression linéaire sous-fitte largement les données.</p><p class="paragraph" style="text-align:left;">Pour construire le modèle classification + régression, on peut utiliser la librairie <code>sklego</code>, qui propose des blocs supplémentaires pour les pipelines scikit-learn. Elle fournit notamment la classe <code>ZeroInflatedRegressor</code>, qui permet de définir un pipeline sklearn avec un <code>DecisionTreeClassifier</code> suivi d&#39;un modèle <code>LinearRegression</code>.</p><p class="paragraph" style="text-align:left;">On l&#39;installe comme suit :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3e715dbf-3507-42c8-a5c8-3f2d713ce25b/Mini-cours__33_-_Code1.png?t=1781039514"/></div><p class="paragraph" style="text-align:left;">On entraîne ensuite le modèle <code>ZeroInflatedRegressor</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c8a23099-93d7-49e2-9b96-d3dbb5005d69/Mini-cours__33_-_Code2.png?t=1781039565"/></div><p class="paragraph" style="text-align:left;">En visualisant le fit, on obtient :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f8f723fd-53d6-445a-9037-a908a6070373/Mini-cours__33_-_Decision_Tree_Classifier_%2B_Re%CC%81gression_Line%CC%81aire.png?t=1781039630"/></div><p class="paragraph" style="text-align:left;">L&#39;efficacité de la régression zero-inflated par rapport à la régression linéaire classique est évidente :</p><ul><li><p class="paragraph" style="text-align:left;">La régression linéaire seule sous-fittait les données.</p></li><li><p class="paragraph" style="text-align:left;">La régression linéaire combinée à un classifier performe comme attendu.</p></li></ul><hr class="content_break"><div class="section" style="background-color:#1B3A6B;border-color:#F7931E;border-radius:8px;border-style:solid;border-width:3px;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;">💡<span style="color:#FFFFFF;"> En continuant, tu vas découvrir : </span></p><ul><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Comment encoder correctement les features cycliques (heure, jour, saison) pour ne pas perdre d&#39;information</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">Breathing KMeans : l&#39;upgrade puissant de KMeans qui converge mieux et plus vite</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">La focal loss : comment gérer les datasets déséquilibrés sans sacrifier les classes minoritaires</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#FFFFFF;">La classification ordinale : pourquoi la cross-entropy échoue sur les labels ordonnés, et comment y remédier</span></p></li></ul></div><div class="paywall"><hr class="paywall__break"/><div class="paywall__content"><h2 class="paywall__header"> La suite de ce mini-cours est réservée aux membres du Cercle des Experts. </h2><p class="paywall__description"> Tu as déjà le début. Pour accéder à l’explication complète et à tous les contenus avancés, rejoins le Cercle des Experts dès maintenant. </p><p class="paywall__links"><a class="paywall__upgrade_link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-2">Rejoindre le Cercle des Experts</a> Translation missing: en.app.shared.conjuction.or <a class="paywall__login_link" href="https://www.monshotdata.com/login?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-2">Sign In</a></p><div class="paywall__upsell"><div class="paywall__upsell_header"><h3> En devenant membre, tu débloques </h3></div><ul class="paywall__upsell_features"><li class="paywall__upsell_feature"> L’intégralité de ce mini-cours (sans coupure) </li><li class="paywall__upsell_feature"> Tous les mini-cours archivés et les ressources associées </li><li class="paywall__upsell_feature"> 1 nouveau mini-cours chaque semaine pour progresser en continu </li></ul></div></div></div></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=a622966c-863f-4521-8de0-245597f3a05e&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Boucle for vs list comprehension : une différence fondamentale</title>
  <description>🎯 Shot #314 - Pourquoi ta variable de boucle survit dans un cas mais pas dans l&#39;autre.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/34ab528f-4958-4c9b-a004-57b670f2ff73/_314_-_Code5.png.png" length="481734" type="image/png"/>
  <link>https://www.monshotdata.com/p/boucle-for-vs-list-comprehension-une-diff-rence-fondamentale</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/boucle-for-vs-list-comprehension-une-diff-rence-fondamentale</guid>
  <pubDate>Mon, 08 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-08T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Python]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">&quot;Les boucles for et les list comprehensions fonctionnent de la même manière et font la même chose.&quot;</p><p class="paragraph" style="text-align:left;">C&#39;est une affirmation qu&#39;on retrouve dans quasi tous les cours, vidéos et blogs d&#39;introduction à Python (ou une variante de cette affirmation… tu vois l&#39;idée).</p><p class="paragraph" style="text-align:left;">Mais ce n&#39;est pas tout à fait vrai.</p><p class="paragraph" style="text-align:left;">Bien sûr, en termes d&#39;objectif, elles font exactement la même chose, et je ne dis pas le contraire.</p><p class="paragraph" style="text-align:left;">Mais ce que la plupart des développeurs Python ignorent, c&#39;est qu&#39;il existe une différence assez subtile dans la façon dont une list comprehension et une boucle for fonctionnent en interne au niveau du scope. Et c&#39;est quelque chose que tout développeur Python devrait connaître.</p><p class="paragraph" style="text-align:left;">Aujourd&#39;hui, je veux partager ça avec toi.</p><p class="paragraph" style="text-align:left;">C&#39;est parti !</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Prenons ce simple code avec une boucle for :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f721db61-99f5-4000-98b6-4f04e2c95716/_314_-_Code1.png?t=1780866525"/></div><p class="paragraph" style="text-align:left;">Après l&#39;exécution de cette boucle for, si on essaie d&#39;accéder à la variable de boucle (<code>loop_var</code>), on constate que la variable est toujours accessible, comme illustré ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/2dd20934-c9a0-4259-b216-6082337d6f18/_314_-_Code2.png?t=1780866565"/></div><p class="paragraph" style="text-align:left;">Jusque-là, tout va bien.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Maintenant, faisons la même chose avec une list comprehension. Le code suivant est l&#39;équivalent en list comprehension de la boucle for ci-dessus :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/bbe9c213-b10c-476c-8310-bd0bb2efeb0b/_314_-_Code3.png.png?t=1780866627"/></div><p class="paragraph" style="text-align:left;">Après l&#39;exécution de cette list comprehension, si on essaie d&#39;accéder à la variable de boucle (<code>loop_var</code>), on constate que la variable n&#39;est PAS accessible :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/247a8604-dd10-4b7e-a2c4-da8270a07068/_314_-_Code4.png.png?t=1780866658"/></div><p class="paragraph" style="text-align:left;">Étrange, non ?</p><p class="paragraph" style="text-align:left;">Pourquoi la variable de boucle est-elle accessible avec une boucle for, mais pas avec une list comprehension ?</p><hr class="content_break"><p class="paragraph" style="text-align:left;">Cela nous amène à une différence essentielle dans le fonctionnement fondamental de la boucle for et de la list comprehension. Et c&#39;est un point que la plupart des tutoriels Python n&#39;abordent pas.</p><p class="paragraph" style="text-align:left;">Quand on utilise une boucle for, Python laisse &quot;fuiter&quot; la variable de boucle dans le scope englobant. <b>Autrement dit, on peut toujours accéder à la variable de boucle une fois la boucle terminée.</b></p><p class="paragraph" style="text-align:left;">Mais une list comprehension ne fonctionne pas de cette manière. La variable de boucle reste toujours locale à la list comprehension et ne fuite jamais à l&#39;extérieur.</p><p class="paragraph" style="text-align:left;">De plus, si on utilise une variable préexistante comme variable de boucle, la boucle for mettra à jour sa valeur, tandis que la list comprehension la laissera inchangée.</p><p class="paragraph" style="text-align:left;">On peut le vérifier sur l&#39;image ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/34ab528f-4958-4c9b-a004-57b670f2ff73/_314_-_Code5.png.png?t=1780866690"/></div><p class="paragraph" style="text-align:left;">La valeur de la variable existante (<code>loop_var</code>) :</p><ul><li><p class="paragraph" style="text-align:left;">est mise à jour quand elle est utilisée dans une boucle for.</p></li><li><p class="paragraph" style="text-align:left;">reste inchangée quand elle est utilisée dans une list comprehension.</p></li></ul><p class="paragraph" style="text-align:left;">La list comprehension ne met pas à jour la valeur parce que, comme on l&#39;a vu plus haut, elle crée une copie locale de la variable de boucle.</p><p class="paragraph" style="text-align:left;">Cette discussion est étroitement liée au concept de &quot;scope&quot; en Python, qui peut être de quatre types et constitue un sujet fondamental en Python.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi de jouer :</b> quels sont les autres concepts techniques de Python que la plupart des développeurs interprètent mal ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=548e2dae-783b-4b50-b0af-a3f055d28996&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Rends tes graphiques Matplotlib ultra-nets avec une seule ligne de code</title>
  <description>🎯 Shot #313 - Le hack SVG qui change tout dans Jupyter Notebook.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/3e69d615-d9c4-4292-b91a-8e33175f95e7/_313_-_Graphiques_Matplotlib_ultra-nets.png" length="32638" type="image/png"/>
  <link>https://www.monshotdata.com/p/matplotlib-graphiques-nets-svg-jupyter</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/matplotlib-graphiques-nets-svg-jupyter</guid>
  <pubDate>Fri, 05 Jun 2026 08:00:00 +0000</pubDate>
  <atom:published>2026-06-05T08:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Visualisation De Données]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Matplotlib a toujours été ma librairie de référence pour la visualisation de données.</p><p class="paragraph" style="text-align:left;">Mais il y a un truc qui me dérange quand je l&#39;utilise dans Jupyter Notebook : les graphiques deviennent ternes et flous dès qu&#39;on les agrandit ou qu&#39;on zoome dessus.</p><p class="paragraph" style="text-align:left;">C&#39;est flagrant sur l&#39;image ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5c8d51b9-018c-457e-89dd-7a610ae32c03/_313_-_Graphique_flou.png.png?t=1780613911"/></div><p class="paragraph" style="text-align:left;">Pourquoi ? </p><p class="paragraph" style="text-align:left;">Parce que par défaut, Matplotlib rend ses graphiques sous forme d&#39;image. Du coup, le moindre agrandissement ou zoom dégrade fortement leur qualité.</p><p class="paragraph" style="text-align:left;">Si tu utilises Matplotlib régulièrement dans Jupyter Notebook, tu as forcément déjà remarqué ça toi aussi.</p><p class="paragraph" style="text-align:left;">Pourtant, il existe un hack plutôt sympa pour améliorer leur qualité de façon spectaculaire.</p><p class="paragraph" style="text-align:left;">Au lieu du rendu image par défaut, commence à générer tes graphiques en <b>SVG (scalable vector graphic)</b>, autrement dit en image vectorielle.</p><p class="paragraph" style="text-align:left;">Comme son nom l&#39;indique, ce format peut être mis à l&#39;échelle sans aucune perte de qualité, ce qui saute aux yeux sur l&#39;image ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/87c53551-b1ff-4794-a278-f76d56b67588/_313_-_Graphique_net.png.png?t=1780613993"/></div><p class="paragraph" style="text-align:left;">Comme le montre l&#39;image ci-dessus, le graphique rendu en SVG surclasse clairement le graphique par défaut. Il reste bien plus net, même en zoomant.</p><p class="paragraph" style="text-align:left;">Le code suivant te permet de basculer le format de rendu en SVG.</p><div class="codeblock"><pre><code>from matplotlib_inline.backend_inline import set_matplotlib_formats
set_matplotlib_formats(&#39;svg&#39;)</code></pre></div><p class="paragraph" style="text-align:left;">Tu peux aussi utiliser celui-ci :</p><div class="codeblock"><pre><code>%config InlineBackend.figure_format = &#39;svg&#39;</code></pre></div><p class="paragraph" style="text-align:left;">Si la différence ne te paraît pas évidente sur l&#39;image ci-dessus, je te conseille vraiment de l&#39;essayer pour la constater par toi-même.</p><p class="paragraph" style="text-align:left;">Télécharge ce Jupyter Notebook pour tester : <a class="link" href="https://docs.moncoachdata.com/w/MGrwUOQ?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=rends-tes-graphiques-matplotlib-ultra-nets-avec-une-seule-ligne-de-code" target="_blank" rel="noopener noreferrer nofollow">Notebook Matplotlib-SVG</a>.</p><hr class="content_break"><p class="paragraph" style="text-align:left;"><b>👉 À toi de jouer :</b> quels autres hacks Matplotlib sympas connais-tu ?</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=e8914f92-d5f8-4ece-9c44-ba79b1620bd5&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Pourquoi tu devrais éviter de déployer des modèles Sklearn en production</title>
  <description>🎯 Shot #312 - Et comment les rendre jusqu&#39;à 40x plus rapides grâce aux calculs tensoriels.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/cfd17d57-861d-4d0b-a508-aaf7aa5a74d7/_312_-_Pourquoi_tu_devrais_e%CC%81viter_de_de%CC%81ployer_des_mode%CC%80les_Sklearn_en_production.png" length="68106" type="image/png"/>
  <link>https://www.monshotdata.com/p/deployer-modeles-sklearn-production</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/deployer-modeles-sklearn-production</guid>
  <pubDate>Mon, 01 Jun 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-06-01T10:00:00Z</atom:published>
    <category><![CDATA[Deep Learning]]></category>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
    <category><![CDATA[Numpy]]></category>
    <category><![CDATA[Sklearn]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">Sklearn est LA librairie de référence pour toutes sortes de tâches de machine learning (ML) traditionnel.</p><p class="paragraph" style="text-align:left;">Mais les choses deviennent vite préoccupantes dès qu&#39;on veut déployer N&#39;IMPORTE QUEL modèle basé sur sklearn.</p><p class="paragraph" style="text-align:left;">Pourquoi ?</p><p class="paragraph" style="text-align:left;">C&#39;est ce qu&#39;on va comprendre aujourd&#39;hui.</p><p class="paragraph" style="text-align:left;">Les modèles sklearn reposent essentiellement sur NumPy, qui s&#39;exécute TOUJOURS sur un seul cœur de CPU.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f544bfed-c94d-4398-8889-07c2b8e9b9a3/_312_-_NumPy_n_utilise_qu_un_seul_c%C5%93ur.png?t=1780301141"/><div class="image__source"><span class="image__source_text"><p>NumPy n&#39;utilise qu&#39;un seul cœur</p></span></div></div><p class="paragraph" style="text-align:left;">Ça laisse une marge de progression énorme, car il n&#39;y a aucune parallélisation. Et ça devient logiquement <b>un vrai problème</b> pour les équipes data qui voudraient confier leurs systèmes de production à sklearn.</p><p class="paragraph" style="text-align:left;">Autre limitation majeure : les modèles scikit-learn ne peuvent pas tourner sur GPU.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/33b5e9ce-9977-489e-bc3e-3292be2d226f/_312_-_Les_mode%CC%80les_Sklearn_tournent_sur_CPU_mais_pas_sur_GPU.png?t=1780301193"/><div class="image__source"><span class="image__source_text"><p>Les modèles Sklearn tournent sur CPU mais pas sur GPU</p></span></div></div><p class="paragraph" style="text-align:left;">Les GPU sont importants parce que beaucoup de systèmes déployés exigent des prédictions ultra-rapides.</p><p class="paragraph" style="text-align:left;">Pourtant, reposant entièrement sur NumPy (qui ne tourne que sur CPU), les modèles sklearn ne peuvent pas s&#39;exécuter sur GPU.</p><p class="paragraph" style="text-align:left;">Malgré tout, il existe une façon d&#39;activer le support GPU sur les modèles sklearn et d&#39;accélérer massivement l&#39;inférence.</p><p class="paragraph" style="text-align:left;">L&#39;idée centrale : compiler un modèle de ML traditionnel déjà entraîné (un random forest, par exemple) en calculs tensoriels.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0db4a5b5-9cf1-4ec4-bd83-f01091399d06/_312_-_Compile_le_mode%CC%80le_sklearn_en_mode%CC%80le_tensoriel.png?t=1780301220"/><div class="image__source"><span class="image__source_text"><p>Compile le modèle sklearn en modèle tensoriel</p></span></div></div><p class="paragraph" style="text-align:left;">Reposant désormais sur des tenseurs, le modèle peut profiter sans friction des fonctionnalités offertes par les systèmes d&#39;inférence basés sur le deep learning, comme :</p><ul><li><p class="paragraph" style="text-align:left;">La facilité de déploiement.</p></li><li><p class="paragraph" style="text-align:left;">Le chargement sur des accélérateurs matériels.</p></li><li><p class="paragraph" style="text-align:left;">L&#39;accélération de l&#39;inférence grâce au support GPU.</p></li></ul><p class="paragraph" style="text-align:left;">L&#39;efficacité de cette technique de compilation saute aux yeux sur l&#39;image ci-dessous : </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ebdecb6-9090-40b0-86f7-5d803f8784c6/_312_-_Mode%CC%80le_Random_Forest_Sklearn_standard_vs._mode%CC%80le_RF_tensoriel_sur_CPU_vs._mode%CC%80le_RF_tensoriel_sur_GPU.png.png?t=1780301279"/><div class="image__source"><span class="image__source_text"><p>Modèle Random Forest Sklearn standard vs. modèle RF tensoriel sur CPU vs. modèle RF tensoriel sur GPU</p></span></div></div><ul><li><p class="paragraph" style="text-align:left;">Ici, on a entraîné un modèle random forest.</p></li></ul><ul><li><p class="paragraph" style="text-align:left;">Le modèle compilé tourne :</p><ul><li><p class="paragraph" style="text-align:left;">Plus de deux fois plus vite sur CPU.</p></li><li><p class="paragraph" style="text-align:left;"><b>Environ 40 fois plus vite sur GPU, ce qui est énorme.</b></p></li></ul></li><li><p class="paragraph" style="text-align:left;">Tous les modèles affichent la même accuracy, signe qu&#39;aucune information n&#39;est perdue pendant la compilation.</p></li></ul><p class="paragraph" style="text-align:left;">Maintenant, si tu te demandes :</p><ul><li><p class="paragraph" style="text-align:left;">Quelles sont ces stratégies de compilation ?</p></li><li><p class="paragraph" style="text-align:left;">Comment fonctionnent-elles ?</p></li><li><p class="paragraph" style="text-align:left;">Comment les implémenter ?</p></li><li><p class="paragraph" style="text-align:left;">Comment représenter un random forest sous forme de calculs matriciels, alors que ça n&#39;a rien d&#39;intuitif ?</p></li></ul><p class="paragraph" style="text-align:left;">...c&#39;est exactement ce qu&#39;on a exploré dans un récent deep dive machine learning : </p><div class="embed"><a class="embed__url" href="https://www.monshotdata.com/p/sklearn-gpu-hummingbird-tenseurs-inference?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=pourquoi-tu-devrais-eviter-de-deployer-des-modeles-sklearn-en-production" target="_blank"><div class="embed__content"><p class="embed__title"> Accélère tes modèles sklearn jusqu&#39;à 40x sans changer ton code </p><p class="embed__description"> Découvre comment compiler tes modèles sklearn en opérations tensorielles PyTorch et les faire tourner sur GPU grâce à Hummingbird — sans réécrire ton code. </p></div><img class="embed__image embed__image--right" src="https://beehiiv-images-production.s3.amazonaws.com/uploads/asset/file/35353cb7-4f97-4bac-bc1b-c67d90c5b5a0/Mini-cours__29_-_Mode%CC%80le_tensoriel_sur_GPU.png?t=1777063248"/></a></div><p class="paragraph" style="text-align:left;">Le temps d&#39;inférence est une métrique business critique dans le déploiement de modèles de ML.</p><p class="paragraph" style="text-align:left;">Comme les entreprises travaillent surtout sur des données tabulaires, les techniques de ML classique comme les modèles linéaires et les méthodes d&#39;ensemble à base d&#39;arbres sont essentielles pour les modéliser.</p><p class="paragraph" style="text-align:left;">Pourtant, dans le paysage actuel, on se retrouve souvent forcé d&#39;entraîner et de déployer des modèles de deep learning, juste parce qu&#39;ils offrent des opérations matricielles optimisées via des tenseurs qu&#39;on peut charger sur GPU.</p><p class="paragraph" style="text-align:left;">Apprendre ces techniques de compilation et les utiliser m&#39;a énormément aidé à déployer <b>des modèles de ML classique avec support GPU</b>.</p><p class="paragraph" style="text-align:left;">Donc, les maîtriser te sera extrêmement précieux si tu envisages d&#39;en faire autant.</p><hr class="content_break"><p class="paragraph" style="text-align:left;">👉 Si ça t&#39;intéresse, c&#39;est à lire ici : <a class="link" href="https://www.monshotdata.com/p/sklearn-gpu-hummingbird-tenseurs-inference?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=pourquoi-tu-devrais-eviter-de-deployer-des-modeles-sklearn-en-production" target="_blank" rel="noopener noreferrer nofollow">Les modèles Sklearn ne sont pas faits pour le déploiement ! Booste-les avec les calculs tensoriels</a>.</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=4c5bcdb2-a83e-4abe-8a68-e9f3bdf42052&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Booste tes modèles ML sans changer d&#39;algorithme (Partie 1)</title>
  <description>👀​ Mini-cours #32 - kNN pondéré, discrétisation de features, label smoothing : les ajustements que les bons data scientists font et que les autres ignorent.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6eb7f75d-c563-490c-96e9-6939757e60bd/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-3.png" length="142933" type="image/png"/>
  <link>https://www.monshotdata.com/p/techniques-ml-avancees-regression-huber-knn-label-smoothing</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/techniques-ml-avancees-regression-huber-knn-label-smoothing</guid>
  <pubDate>Thu, 28 May 2026 09:00:00 +0000</pubDate>
  <atom:published>2026-05-28T09:00:00Z</atom:published>
    <category><![CDATA[Machine Learning]]></category>
    <category><![CDATA[Qualité &amp; Architecture]]></category>
    <category><![CDATA[Pro]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><div class="section" style="background-color:#f2eafe;border-radius:8px;margin:0.0px 0.0px 0.0px 0.0px;padding:2.0px 2.0px 2.0px 2.0px;"><p class="paragraph" style="text-align:left;"><span style="text-decoration:underline;"><b>Psst... Contenu Exclusif Réservé aux Membres !</b></span><br><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Ce mini-cours fait partie de notre espace premium. Rejoins dès maintenant le </span><b>Cercle des Experts</b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;"> pour débloquer l’intégralité de nos ressources, analyses approfondies et guides pratiques.</span><br><b>👉 </b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">Clique ici pour découvrir les avantages et t’inscrire : </span><b><a class="link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-1" target="_blank" rel="noopener noreferrer nofollow" style="color: #2563eb">Page d’adhésion</a></b><span style="color:#3f3f46;font-family:__Figtree_2ca027, __Figtree_Fallback_2ca027, ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;;font-size:16px;">.</span></p></div><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;"><span style="color:#222222;font-family:Poppins, Helvetica, sans-serif, serif, EmojiFont;font-size:16px;">⏱️ </span><i><b>Temps de lecture</b></i><i> : 15-20 minutes</i></p></div><p class="paragraph" style="text-align:left;">Beaucoup d&#39;ingénieurs ML et de data scientists passent trop vite à un nouveau type de modèle dès qu&#39;ils n&#39;obtiennent pas les résultats escomptés avec le modèle en cours.</p><p class="paragraph" style="text-align:left;">On n&#39;exploite pas toujours toutes les possibilités des modèles existants, et on se tourne vers des architectures plus complexes alors que quelques ajustements ciblés sur un modèle simple suffiraient à obtenir des résultats très satisfaisants.</p><p class="paragraph" style="text-align:left;">Au fil de la construction de nombreux modèles ML, j&#39;ai utilisé différentes techniques qui permettent de révéler des nuances et des optimisations capables d&#39;améliorer significativement les performances, sans pour autant augmenter la complexité du modèle.</p><p class="paragraph" style="text-align:left;">Dans ce deep dive, je vais te partager 5 de ces techniques puissantes, issues d&#39;une liste de 11 au total, que tu pourras utiliser immédiatement pour tirer le maximum de tes modèles.</p><p class="paragraph" style="text-align:left;">Pour chacune, je t&#39;explique la motivation derrière son usage, et je te fournis le code correspondant.</p><p class="paragraph" style="text-align:left;">C&#39;est parti.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="technique-1-rendre-la-rgression-lin">Technique #1 : Rendre la régression linéaire robuste aux outliers</h2><h3 class="heading" style="text-align:left;" id="le-problme-des-modles-de-rgression">Le problème des modèles de régression</h3><p class="paragraph" style="text-align:left;">Le problème majeur de la plupart des modèles de régression, c&#39;est leur sensibilité aux outliers.</p><p class="paragraph" style="text-align:left;">Prenons la régression linéaire, par exemple.</p><p class="paragraph" style="text-align:left;">Même quelques outliers peuvent impacter significativement ses performances, comme illustré ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8753aaff-ad79-4055-b71a-3ba7270c0993/Mini-cours__32_-_Deux_outliers_suffisent_a%CC%80_de%CC%81former_le_fit_de_re%CC%81gression.png?t=1779915922"/></div><p class="paragraph" style="text-align:left;">La cause de ce problème n&#39;est pas difficile à identifier.</p><p class="paragraph" style="text-align:left;">La fonction de loss MSE (Mean Squared Error) croît rapidement avec le terme résiduel (vrai - prédit) :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/c7e4f94e-c194-47af-96ad-799cd05e0863/Mini-cours__32_-_L_erreur_croi%CC%82t_rapidement_avec_le_terme_re%CC%81siduel.png?t=1779915962"/></div><p class="paragraph" style="text-align:left;">Ainsi, même quelques points de données avec un résidu élevé peuvent fortement influencer l&#39;estimation des paramètres.</p><h3 class="heading" style="text-align:left;" id="la-rgression-de-huber">La régression de Huber</h3><p class="paragraph" style="text-align:left;"><b>La Huber loss (utilisée par la régression de Huber) répond précisément à ce problème.</b></p><p class="paragraph" style="text-align:left;">En résumé, elle cherche à réduire la contribution des points de données ayant un résidu élevé.</p><p class="paragraph" style="text-align:left;">Comment ?</p><p class="paragraph" style="text-align:left;">Une façon simple, intuitive et évidente d&#39;y parvenir consiste à appliquer un seuil (<code>δ</code>) sur le terme résiduel :</p><ul><li><p class="paragraph" style="text-align:left;">Si le résidu est inférieur au seuil, on utilise la MSE (aucun changement).</p></li><li><p class="paragraph" style="text-align:left;">Sinon, on utilise une fonction de loss dont la sortie est plus petite que la MSE, une fonction linéaire, par exemple.</p></li></ul><p class="paragraph" style="text-align:left;">C&#39;est ce qu&#39;illustre le schéma ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/f6ce1d07-aa2b-4e2c-8ff8-fe15f2e64a9e/Mini-cours__32_-_Huber_loss.png?t=1779916014"/></div><ul><li><p class="paragraph" style="text-align:left;">Pour les résidus inférieurs au seuil (<code>δ</code>), on utilise la MSE.</p></li><li><p class="paragraph" style="text-align:left;">Sinon, on applique une fonction de loss linéaire, dont la sortie est plus faible que celle de la MSE.</p></li></ul><p class="paragraph" style="text-align:left;">Mathématiquement, la Huber loss est définie comme suit :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/4ff51d91-e06c-4918-b876-740a624c2d4a/Mini-cours__32_-_Maths_derrie%CC%80re_Huber_loss.png?t=1779916039"/></div><h3 class="heading" style="text-align:left;" id="exprience">Expérience</h3><p class="paragraph" style="text-align:left;">Prenons le dataset 2D fictif présenté plus haut. </p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/53a43c56-93f4-4214-af04-fcacf5339cf2/Mini-cours__32_-_Code1.png?t=1779916061"/></div><p class="paragraph" style="text-align:left;">Pour l&#39;instant, ce dataset ne contient aucun outlier. Ajoutons-en quelques-uns :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/043f2ca5-7e9d-4e35-a3f1-cad6e58f525f/Mini-cours__32_-_Code2.png?t=1779916097"/></div><p class="paragraph" style="text-align:left;">On obtient le dataset suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0e6d7bcc-3e13-4f1f-a2d1-10616230bed4/Mini-cours__32_-_Dataset_2D_fictif.png.png?t=1779916167"/></div><p class="paragraph" style="text-align:left;">Entraînons un modèle de régression linéaire sur ce dataset :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1076fe87-5767-46fd-9228-d0625158adb2/Mini-cours__32_-_Code3.png?t=1779916184"/></div><p class="paragraph" style="text-align:left;">On visualise ensuite le fit de régression en traçant les valeurs <code>y_pred</code> :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/1b8b2ce7-46a4-4376-8574-a9af1829d4c9/Mini-cours__32_-_Code4.png?t=1779916210"/></div><p class="paragraph" style="text-align:left;">Ce qui donne le graphique suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/bfb98920-b41c-4143-af2b-128124ce50dd/Mini-cours__32_-_Re%CC%81gression_line%CC%81aire.png?t=1779916230"/></div><p class="paragraph" style="text-align:left;">Il est clair que la régression linéaire est affectée par les outliers.</p><p class="paragraph" style="text-align:left;">Regardons maintenant la régression de Huber, qui, comme on l&#39;a vu, applique une pénalité linéaire à tous les résidus supérieurs au seuil <code>δ</code>.</p><p class="paragraph" style="text-align:left;">Pour entraîner un modèle de régression de Huber, on reprend les mêmes étapes, mais cette fois avec la classe <code>HuberRegressor</code> de sklearn.</p><p class="paragraph" style="text-align:left;">On obtient le fit de régression suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/8b420305-8faa-45cc-a0a1-840cb4cde32f/Mini-cours__32_-_Re%CC%81gression_de_Huber.png.png?t=1779916275"/></div><p class="paragraph" style="text-align:left;">La robustesse de la régression de Huber est évidente.</p><h3 class="heading" style="text-align:left;" id="comment-choisir">Comment choisir δ ?</h3><p class="paragraph" style="text-align:left;">Le trial and error est une option, mais construire un graphique des résidus est bien plus utile. Voici comment procéder :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/91076d39-6b53-4f11-a6ac-96e54152f39b/Mini-cours__32_-_Un_choix_raisonnable_pour_le_seuil.png?t=1779916312"/></div><ul><li><p class="paragraph" style="text-align:left;"><b>Étape 1</b> : Entraîne un modèle de régression linéaire classique sur le dataset contenant les outliers.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/27afb906-91e7-42c4-b645-4acada3553f3/Mini-cours__32_-_Code5.png?t=1779916349"/></div><ul><li><p class="paragraph" style="text-align:left;"><b>Étape 2</b> : Calcule la valeur absolue des résidus (= vrai - prédit) sur les données d&#39;entraînement.</p></li></ul><p class="paragraph" style="text-align:left;"></p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/76727d98-d877-48ee-9c49-9994f2942fcf/Mini-cours__32_-_Code6.png?t=1779916372"/></div><ul><li><p class="paragraph" style="text-align:left;"><b>Étape 3</b> : Trace le tableau des résidus absolus pour chaque point de données.</p></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/22c39bb4-f143-4846-91fd-56740e0223cc/Mini-cours__32_-_Code7.png?t=1779916400"/></div><p class="paragraph" style="text-align:left;">Ce qui donne le graphique suivant :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/82ce37e5-e0e9-4f73-a244-06c8e829335a/Mini-cours__32_-_Graphique_des_re%CC%81sidus.png.png?t=1779916472"/></div><p class="paragraph" style="text-align:left;">D&#39;après ce graphique, <code>δ = 4</code> semble être une bonne valeur seuil.</p><p class="paragraph" style="text-align:left;">L&#39;avantage de cette approche, c&#39;est qu&#39;elle fonctionne pour un dataset de n&#39;importe quelle dimensionnalité. On ne fait que tracer les valeurs (vrai - prédit), qui sont toujours en 1D.</p><p class="paragraph" style="text-align:left;">L&#39;idée centrale reste la même : réduire la contribution des outliers dans le fit de régression.</p><hr class="content_break"><h2 class="heading" style="text-align:left;" id="techniques-2-et-3-booster-les-modle">Techniques #2 et #3 : Booster les modèles kNN</h2><h3 class="heading" style="text-align:left;" id="le-problme-des-k-n-ns">Le problème des kNNs</h3><p class="paragraph" style="text-align:left;">Ce qui me rend toujours un peu prudent avec les kNNs, c&#39;est leur forte sensibilité au paramètre k.</p><p class="paragraph" style="text-align:left;">Pour mieux comprendre, considère ce dataset 2D fictif ci-dessous. Le point rouge est une instance de test pour laquelle on souhaite générer une prédiction avec un kNN.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/98e5f152-486d-4e71-b831-f69bbfe6f993/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-1.png?t=1779916499"/></div><p class="paragraph" style="text-align:left;">Supposons <code>k = 7</code>.</p><p class="paragraph" style="text-align:left;">La prédiction pour le point rouge se fait en deux étapes :</p><ol start="1"><li><p class="paragraph" style="text-align:left;">On identifie les <code>7</code> voisins les plus proches du point rouge.</p></li><li><p class="paragraph" style="text-align:left;">On lui attribue la classe la plus représentée parmi ces <code>7</code> voisins.</p></li></ol><p class="paragraph" style="text-align:left;">C&#39;est ce qu&#39;illustre le schéma ci-dessous :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/144c3d50-e6c2-4382-a91d-56fe377856ff/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-2.png?t=1779916515"/></div><p class="paragraph" style="text-align:left;">Le problème, c&#39;est que l&#39;étape 2 repose entièrement sur la notion de contribution de classe : la classe qui contribue le plus parmi les <code>k</code> voisins les plus proches est celle qui est attribuée au point de données.</p><p class="paragraph" style="text-align:left;">Mais cette notion échoue parfois, notamment quand une classe est peu représentée.</p><p class="paragraph" style="text-align:left;">Par exemple, avec <code>k = 7</code>, le point rouge ne pourra JAMAIS être attribué à la classe jaune, aussi proche qu&#39;il soit de ce cluster :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6eb7f75d-c563-490c-96e9-6939757e60bd/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-3.png?t=1779916534"/></div><p class="paragraph" style="text-align:left;">Si ajuster visuellement <code>k</code> est facile sur cet exemple, la démarche devient inapplicable sur des datasets haute dimensionnalité.</p><p class="paragraph" style="text-align:left;">Il existe deux façons d&#39;y remédier.</p><hr class="content_break"><h3 class="heading" style="text-align:left;" id="solution-1-k-nn-pondr-par-la-distan">Solution #1 : kNN pondéré par la distance</h3><p class="paragraph" style="text-align:left;">Le kNN pondéré par la distance est une alternative bien plus robuste au kNN classique.</p><p class="paragraph" style="text-align:left;">Comme son nom l&#39;indique, à l&#39;étape 2, on tient compte de la distance par rapport au voisin le plus proche. Résultat : plus un voisin est proche, plus il a d&#39;impact sur la prédiction finale.</p><p class="paragraph" style="text-align:left;">Prenons ce dataset 2D fictif :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/0944f3dc-4283-4c3c-9dc1-08a98f60eda5/Mini-cours__32_-_dataset_2D_fictif_avec_2_classes.png.png?t=1779916583"/></div><p class="paragraph" style="text-align:left;">Avec une instance de test fictive :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/011ea517-d32f-4d83-b741-462600a823b7/Mini-cours__32_-_instance_de_test_fictive.png.png?t=1779916623"/></div><p class="paragraph" style="text-align:left;">En entraînant un kNN classifier avec la stratégie uniforme (basée sur le comptage), le modèle prédit la <code>Classe 0</code> (le rouge) pour la nouvelle instance :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7a6a331e-c694-466c-9c6b-cb902bd37910/Mini-cours__32_-_Code8.png?t=1779916663"/></div><p class="paragraph" style="text-align:left;">En revanche, le kNN pondéré par la distance se révèle plus robuste :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/a518448e-1b60-48c4-aaba-1d162290ebe5/Mini-cours__32_-_Code9.png?t=1779916678"/></div><p class="paragraph" style="text-align:left;">Cette fois, on obtient la <code>Classe 1</code> (le bleu), ce qui est correct.</p><p class="paragraph" style="text-align:left;">D&#39;après mon expérience, un kNN pondéré par la distance fonctionne généralement bien mieux qu&#39;un kNN classique. C&#39;est d&#39;ailleurs intuitif.</p><p class="paragraph" style="text-align:left;">Pourtant, cette option passe souvent inaperçue : par défaut, l&#39;implémentation kNN de sklearn utilise une pondération uniforme.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/30c1f66b-d923-43a2-a539-149ba3a07b4f/Mini-cours__32_-_La_valeur_par_de%CC%81faut_est__uniform_.png.png?t=1779916772"/></div><hr class="content_break"><h3 class="heading" style="text-align:left;" id="solution-2-mise-jour-dynamique-du-p">Solution #2 : Mise à jour dynamique du paramètre k</h3><p class="paragraph" style="text-align:left;">Rappelle-toi le schéma de départ :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6eb7f75d-c563-490c-96e9-6939757e60bd/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-3.png?t=1779916534"/></div><p class="paragraph" style="text-align:left;">On pourrait arguer qu&#39;il faut éviter de fixer <code>k</code> à une valeur supérieure au nombre minimal d&#39;exemples appartenant à une classe dans le dataset.</p><p class="paragraph" style="text-align:left;">Je suis d&#39;accord dans une certaine mesure, mais voici le revers de la médaille.</p><p class="paragraph" style="text-align:left;">Fixer une valeur de <code>k</code> trop faible peut s&#39;avérer très problématique sur des datasets fortement déséquilibrés.</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/7439b089-c95b-4fef-9ad5-be1c3cfa8039/Mini-cours__32_-_Distribution_des_classes.png?t=1779916832"/></div><p class="paragraph" style="text-align:left;">Pour te donner une idée concrète : j&#39;ai personnellement utilisé des kNNs sur des datasets où une classe ne comptait qu&#39;une ou deux instances dans le training set.</p><p class="paragraph" style="text-align:left;">Et j&#39;ai constaté qu&#39;un <code>k</code> trop faible (1 ou 2) produisait des performances sous-optimales, car le modèle n&#39;évaluait pas les patterns de voisinage de façon assez globale, contrairement à ce qu&#39;il faisait avec un <code>k</code> plus élevé.</p><p class="paragraph" style="text-align:left;">En d&#39;autres termes, un <code>k</code> plus grand donne généralement des prédictions plus éclairées qu&#39;un <code>k</code> faible.</p><p class="paragraph" style="text-align:left;">Mais on vient de voir que si <code>k</code> est trop grand, la classe majoritaire peut dominer la classification :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/6eb7f75d-c563-490c-96e9-6939757e60bd/Mini-cours__32_-_Le_proble%CC%80me_des_kNNs-3.png?t=1779916534"/></div><p class="paragraph" style="text-align:left;">Pour résoudre ce problème, j&#39;ai trouvé que la mise à jour dynamique de <code>k</code> était bien plus efficace.</p><p class="paragraph" style="text-align:left;">Voici les trois étapes de cette approche, appliquées à chaque point de données de test :</p><ul><li><p class="paragraph" style="text-align:left;"><b>Étape 1</b> : Commence avec une valeur standard de <code>k</code> et identifie les <code>k</code> voisins les plus proches.</p></li><li><p class="paragraph" style="text-align:left;"><b>Étape 2</b> : Mets à jour la valeur de <code>k</code> comme suit :</p><ul><li><p class="paragraph" style="text-align:left;">Pour toutes <b>les classes uniques présentes parmi les </b><code>k</code><b> voisins les plus proches</b>, identifie le nombre total d&#39;instances d&#39;entraînement qu&#39;elles comportent.</p></li></ul></li></ul><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/97d7799b-9c93-419e-ac02-dbcf23cf81e3/Mini-cours__32_-_de%CC%81terminer_le_nombre_total_d_instances_des_deux_classes.png.png?t=1779916903"/></div><ul><li><p class="paragraph" style="text-align:left;">Mets à jour <code>k</code> ainsi : <br><code>k′ = min(k, nombre_minimal_d&#39;instances_parmi_les_classes_présentes)</code></p></li></ul><p class="paragraph" style="text-align:left;"><i>Exemple avec les images ci-dessus : les deux classes présentes comptent 40 et 3 instances → </i><code>k′ = min(7, 3) = 3</code></p><ul><li><p class="paragraph" style="text-align:left;"><b>Étape 3</b> : Effectue le vote majoritaire uniquement sur les <code>k′</code> premiers voisins.</p></li></ul><p class="paragraph" style="text-align:left;">Cette approche est intuitivement solide :</p><ul><li><p class="paragraph" style="text-align:left;">Si une classe minoritaire apparaît parmi les <code>k</code> voisins les plus proches, on réduit k pour éviter que la classe majoritaire ne domine.</p></li><li><p class="paragraph" style="text-align:left;">Si une classe minoritaire n&#39;apparaît PAS parmi les <code>k</code> voisins les plus proches, <code>k</code> ne sera vraisemblablement pas mis à jour, et la classification reste globale.</p></li></ul><p class="paragraph" style="text-align:left;">L&#39;inconvénient, c&#39;est qu&#39;il n&#39;existe aucune implémentation open source de cette approche.</p><div class="section" style="background-color:transparent;margin:0.0px 0.0px 0.0px 0.0px;padding:10.0px 10.0px 10.0px 10.0px;"><hr class="content_break"></div><div class="section" style="background-color:#1B3A6B;border-color:#F7931E;border-radius:8px;border-style:solid;border-width:3px;margin:0.0px 0.0px 0.0px 0.0px;padding:0.0px 0.0px 0.0px 0.0px;"><p class="paragraph" style="text-align:left;">💡<span style="color:#F9FAFB;"> En continuant, tu vas découvrir : </span></p><ul><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Comment la discrétisation de features permet à un modèle linéaire d&#39;apprendre des patterns non linéaires</span></p></li><li><p class="paragraph" style="text-align:left;"><span style="color:#F9FAFB;">Le label smoothing : la technique de régularisation sous-estimée qui améliore la généralisation de tes réseaux de neurones</span></p></li></ul></div><div class="paywall"><hr class="paywall__break"/><div class="paywall__content"><h2 class="paywall__header"> La suite de ce mini-cours est réservée aux membres du Cercle des Experts. </h2><p class="paywall__description"> Tu as déjà le début. Pour accéder à l’explication complète et à tous les contenus avancés, rejoins le Cercle des Experts dès maintenant. </p><p class="paywall__links"><a class="paywall__upgrade_link" href="https://www.monshotdata.com/upgrade?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-1">Rejoindre le Cercle des Experts</a> Translation missing: en.app.shared.conjuction.or <a class="paywall__login_link" href="https://www.monshotdata.com/login?utm_source=www.monshotdata.com&utm_medium=newsletter&utm_campaign=booste-tes-modeles-ml-sans-changer-d-algorithme-partie-1">Sign In</a></p><div class="paywall__upsell"><div class="paywall__upsell_header"><h3> En devenant membre, tu débloques </h3></div><ul class="paywall__upsell_features"><li class="paywall__upsell_feature"> L’intégralité de ce mini-cours (sans coupure) </li><li class="paywall__upsell_feature"> Tous les mini-cours archivés et les ressources associées </li><li class="paywall__upsell_feature"> 1 nouveau mini-cours chaque semaine pour progresser en continu </li></ul></div></div></div></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=17b1bb56-e333-4e52-82be-3d86f9b15b01&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

      <item>
  <title>Suivi d&#39;expériences ML : la compétence que personne ne t&#39;a apprise</title>
  <description>🎯 Shot #311 - Sheets, flags manuels, et pipelines qui repartent de zéro : voilà ce que coûte l&#39;absence d&#39;un vrai système de tracking.</description>
      <enclosure url="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/12d89284-61c5-4494-8520-3be323fcecb1/_311_-_Suivi_d_expe%CC%81riences_ML.png" length="38559" type="image/png"/>
  <link>https://www.monshotdata.com/p/suivi-experiences-ml-tracking-pipeline</link>
  <guid isPermaLink="true">https://www.monshotdata.com/p/suivi-experiences-ml-tracking-pipeline</guid>
  <pubDate>Mon, 25 May 2026 10:00:00 +0000</pubDate>
  <atom:published>2026-05-25T10:00:00Z</atom:published>
    <category><![CDATA[Shot Data]]></category>
    <category><![CDATA[Machine Learning]]></category>
  <content:encoded><![CDATA[
    <div class='beehiiv'><style>
  .bh__table, .bh__table_header, .bh__table_cell { border: 1px solid #C0C0C0; }
  .bh__table_cell { padding: 5px; background-color: #FFFFFF; }
  .bh__table_cell p { color: #2D2D2D; font-family: 'Helvetica',Arial,sans-serif !important; overflow-wrap: break-word; }
  .bh__table_header { padding: 5px; background-color:#f0f7ef; }
  .bh__table_header p { color: #153c4f; font-family:'Trebuchet MS','Lucida Grande',Tahoma,sans-serif !important; overflow-wrap: break-word; }
</style><div class='beehiiv__body'><p class="paragraph" style="text-align:left;">D&#39;après mon expérience, la plupart des projets ML n&#39;ont pas de système dédié à la gestion et au suivi des expériences.</p><p class="paragraph" style="text-align:left;">Comme le nom l&#39;indique, ce type de système permet de tracer :</p><ul><li><p class="paragraph" style="text-align:left;"><b>La configuration du modèle</b>, critique pour la reproductibilité.</p></li><li><p class="paragraph" style="text-align:left;"><b>Les performances du modèle</b>, indispensables pour comparer différentes approches.</p></li></ul><p class="paragraph" style="text-align:left;">...et ce, à travers toutes les expériences.</p><p class="paragraph" style="text-align:left;">Pourtant, la plupart des projets ML s&#39;appuient sur des systèmes manuels qui ne capturent que des détails limités :</p><ul><li><p class="paragraph" style="text-align:left;">La performance finale (sans les courbes de convergence époque par époque)</p></li><li><p class="paragraph" style="text-align:left;">Les hyperparamètres, etc.</p></li></ul><p class="paragraph" style="text-align:left;">Or, d&#39;une expérience à l&#39;autre, énormément de choses peuvent changer :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/eb2e72e6-4bbe-4e6c-9887-1f2e0907a863/_311_-_2_expe%CC%81riences.png?t=1779697950"/></div><ul><li><p class="paragraph" style="text-align:left;">Les hyperparamètres</p></li><li><p class="paragraph" style="text-align:left;">Les données</p></li><li><p class="paragraph" style="text-align:left;">Le type de modèle</p></li></ul><p class="paragraph" style="text-align:left;">Tout tracer avec précision peut vite devenir fastidieux et chronophage.</p><p class="paragraph" style="text-align:left;">Et ce n&#39;est pas tout. Imagine que ton pipeline ML comporte trois étapes :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/89bf1ad7-d59e-4a25-aa1e-93afde35682b/_311_-_3_e%CC%81tapes_pipeline_ML.png?t=1779697978"/></div><p class="paragraph" style="text-align:left;">Si tu n&#39;as modifié que l&#39;entraînement du modèle (étape 3), disons que tu as changé un hyperparamètre, est-ce qu&#39;il est utile de relancer les deux premières étapes ?</p><p class="paragraph" style="text-align:left;">Non, clairement pas.</p><p class="paragraph" style="text-align:left;">Pourtant, la plupart des pipelines ML relancent tout depuis le début, gaspillant du temps et des ressources de calcul.</p><p class="paragraph" style="text-align:left;">On peut bien sûr ajouter des flags manuels pour éviter ça :</p><div class="image"><img alt="" class="image__image" style="" src="https://media.beehiiv.com/cdn-cgi/image/fit=scale-down,format=auto,onerror=redirect,quality=80/uploads/asset/file/5711bd57-94a0-4644-b564-222ae3904646/_311_-_Flags_manuels.png?t=1779698863"/></div><p class="paragraph" style="text-align:left;"><b>Mais une solution manuelle reste toujours sujette aux erreurs.</b></p><p class="paragraph" style="text-align:left;">Pour éviter cette friction inutile, un système de suivi efficace doit être capable de :</p><ul><li><p class="paragraph" style="text-align:left;">Détecter tous les changements apportés au pipeline ML.</p></li><li><p class="paragraph" style="text-align:left;">Identifier les étapes qu&#39;il peut éviter de relancer.</p></li><li><p class="paragraph" style="text-align:left;">N&#39;exécuter que les étapes strictement nécessaires pour produire les résultats finaux.</p></li></ul><p class="paragraph" style="text-align:left;">La motivation est évidente. Pourtant, c&#39;est une compétence que beaucoup ignorent, et on continue à voir des systèmes manuels inefficaces partout : Sheets, Docs, et compagnie.</p><hr class="content_break"></div><div class='beehiiv__footer'><br class='beehiiv__footer__break'><hr class='beehiiv__footer__line'><a target="_blank" class="beehiiv__footer_link" style="text-align: center;" href="https://www.beehiiv.com/?utm_campaign=f2679092-3d02-4110-aa87-26f4290a87c8&utm_medium=post_rss&utm_source=mon_shot_de_data_science">Powered by beehiiv</a></div></div>
  ]]></content:encoded>
</item>

  </channel>
</rss>
