{"id":4671,"date":"2026-09-11T11:29:31","date_gmt":"2026-09-11T11:29:31","guid":{"rendered":"http:\/\/french.arabpsychology.com\/statistics\/calculer-distance-euclidienne-python-exemples\/"},"modified":"2026-09-11T11:29:31","modified_gmt":"2026-09-11T11:29:31","slug":"calculer-distance-euclidienne-python-exemples","status":"publish","type":"psych_stat","link":"https:\/\/french.arabpsychology.com\/?psych_stat=calculer-distance-euclidienne-python-exemples","title":{"rendered":"Comment calculer la distance euclidienne en Python (avec exemples)"},"content":{"rendered":"<p>Au c\u0153ur de l&rsquo;analyse computationnelle moderne, de la g\u00e9om\u00e9trie diff\u00e9rentielle et de l&rsquo;apprentissage automatique, la quantification de la proximit\u00e9 spatiale entre entit\u00e9s vectorielles constitue une op\u00e9ration fondamentale. La mesure de cette proximit\u00e9, d\u00e9sign\u00e9e sous l&rsquo;appellation g\u00e9n\u00e9rique de m\u00e9trique de dissimilarit\u00e9, s&rsquo;incarne principalement \u00e0 travers la distance euclidienne. Issue de l&rsquo;h\u00e9ritage g\u00e9om\u00e9trique de la Gr\u00e8ce antique et formalis\u00e9e dans le cadre des espaces euclidiens affines par les travaux de Ren\u00e9 Descartes et Carl Friedrich Gauss, cette mesure repr\u00e9sente la longueur physique g\u00e9od\u00e9sique reliant deux coordonn\u00e9es au sein d&rsquo;un continuum euclidien plat. En sciences des donn\u00e9es contemporaines, elle r\u00e9git le comportement de multiples algorithmes d&rsquo;apprentissage non supervis\u00e9 et supervis\u00e9, gouverne les projections dimensionnelles et permet de comparer des profils empiriques au moyen de repr\u00e9sentations spatiales abstraites.<\/p>\n<p>L&rsquo;impl\u00e9mentation algorithmique de cette mesure au sein de l&rsquo;\u00e9cosyst\u00e8me Python requiert une compr\u00e9hension fine de la dualit\u00e9 entre la s\u00e9mantique de haut niveau du langage et les contraintes bas niveau d&rsquo;allocation de m\u00e9moire vive et de calcul vectoris\u00e9. Python, en tant que langage interpr\u00e9t\u00e9 \u00e0 typage dynamique, pr\u00e9sente des caract\u00e9ristiques d&rsquo;ex\u00e9cution sp\u00e9cifiques qui rendent le choix de la m\u00e9thode de calcul critique d\u00e8s lors que la volum\u00e9trie des observations s&rsquo;accro\u00eet. Une approche na\u00efve fond\u00e9e sur des it\u00e9rateurs standards peut induire un surco\u00fbt d&rsquo;interpr\u00e9tation prohibitif, tandis que le recours aux biblioth\u00e8ques d&rsquo;acc\u00e9l\u00e9ration scientifique transforme radicalement les profils de complexit\u00e9 temporelle gr\u00e2ce \u00e0 l&rsquo;exploitation des instructions vectorielles des microprocesseurs modernes.<\/p>\n<p>Ce trait\u00e9 exhaustif a pour vocation d&rsquo;explorer en profondeur les fondements th\u00e9oriques, les m\u00e9canismes alg\u00e9briques et les impl\u00e9mentations pratiques de la distance euclidienne \u00e0 travers l&rsquo;\u00e9cosyst\u00e8me num\u00e9rique Python. Du code pur d\u00e9nu\u00e9 de toute d\u00e9pendance logicielle externe jusqu&rsquo;aux primitives optimis\u00e9es de <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/\">NumPy<\/a>, <a rel=\"noopener noreferrer\" href=\"https:\/\/scipy.org\/\">SciPy<\/a>, Pandas, Scikit-Learn et <a rel=\"noopener noreferrer\" href=\"https:\/\/numba.pydata.org\/\">Numba<\/a>, chaque approche sera examin\u00e9e \u00e0 la lumi\u00e8re de ses propri\u00e9t\u00e9s algorithmiques, de sa complexit\u00e9 asymptotique et de ses implications dans des contextes applicatifs r\u00e9els, notamment en mod\u00e9lisation psychom\u00e9trique et comportementale.<\/p>\n<h2>1. Fondements th\u00e9oriques et math\u00e9matiques de la distance euclidienne<\/h2>\n<h3>1.1 D\u00e9finition g\u00e9om\u00e9trique et origine cart\u00e9sienne<\/h3>\n<p>La distance euclidienne trouve sa gen\u00e8se dans les postulats de la g\u00e9om\u00e9trie classique formul\u00e9s par <a rel=\"noopener noreferrer\" href=\"https:\/\/mathworld.wolfram.com\/EuclideanSpace.html\">Euclide d&rsquo;Alexandrie<\/a> dans ses <em>\u00c9l\u00e9ments<\/em>, compl\u00e9t\u00e9s au XVIIe si\u00e8cle par l&rsquo;introduction du syst\u00e8me de coordonn\u00e9es cart\u00e9siennes par Ren\u00e9 Descartes. Dans un plan affine euclidien de dimension deux, la distance s\u00e9parant deux points mat\u00e9riels correspond \u00e0 la longueur du segment de droite rectiligne qui les joint. Cette grandeur scalaire d\u00e9coule directement de l&rsquo;application du th\u00e9or\u00e8me de Pythagore : consid\u00e9rant deux entit\u00e9s ponctuelles d\u00e9sign\u00e9es respectivement par les couples de coordonn\u00e9es r\u00e9elles <span class=\"arabpsy-math-inline\" data-latex=\"P = (p_1, p_2)\">$P = (p_1, p_2)$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"Q = (q_1, q_2)\">$Q = (q_1, q_2)$<\/span>, la projection de ces points parall\u00e8lement aux axes orthogonaux engendre un triangle rectangle dont l&rsquo;hypot\u00e9nuse co\u00efncide avec le segment reliant <span class=\"arabpsy-math-inline\" data-latex=\"P\">$P$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"Q\">$Q$<\/span>.<\/p>\n<p>Dans un tel cadre g\u00e9om\u00e9trique, le carr\u00e9 de la longueur du segment d&rsquo;int\u00e9r\u00eat \u00e9quivaut rigoureusement \u00e0 la sommation des carr\u00e9s des longueurs des c\u00f4t\u00e9s adjacents, menant \u00e0 l&rsquo;expression \u00e9l\u00e9mentaire :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"d(P, Q) = \\sqrt{(p_1 - q_1)^2 + (p_2 - q_2)^2}\">$$d(P, Q) = \\sqrt{(p_1 &#8211; q_1)^2 + (p_2 &#8211; q_2)^2}$$<\/span><\/p>\n<p>Cette conceptualisation s&rsquo;\u00e9tend sans rupture \u00e9pist\u00e9mologique \u00e0 l&rsquo;espace tridimensionnel <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbb{R}^3\">$\\mathbb{R}^3$<\/span>. Pour deux positions d\u00e9finies par les triplets <span class=\"arabpsy-math-inline\" data-latex=\"(p_1, p_2, p_3)\">$(p_1, p_2, p_3)$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"(q_1, q_2, q_3)\">$(q_1, q_2, q_3)$<\/span>, le segment spatial se d\u00e9duit par une double application successive de la relation pythagoricienne, traduisant la r\u00e8gle g\u00e9od\u00e9sique selon laquelle la ligne droite constitue le chemin de moindre longueur au sein d&rsquo;un espace topologique dot\u00e9 d&rsquo;une courbure nulle. Cette mod\u00e9lisation cart\u00e9sienne pose ainsi les jalons fondamentaux de la param\u00e9trisation des ph\u00e9nom\u00e8nes physiques et des abstractions multidimensionnelles.<\/p>\n<h3>1.2 Formulation alg\u00e9brique g\u00e9n\u00e9rale en dimension n<\/h3>\n<p>La transition de la g\u00e9om\u00e9trie spatiale intuitive vers l&rsquo;alg\u00e8bre lin\u00e9aire abstraite autorise la g\u00e9n\u00e9ralisation de la distance euclidienne \u00e0 des espaces vectoriels r\u00e9els de dimension arbitraire <span class=\"arabpsy-math-inline\" data-latex=\"n\">$n$<\/span>, d\u00e9sign\u00e9s par <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbb{R}^n\">$\\mathbb{R}^n$<\/span>. Soient deux vecteurs colonnes ou points multidimensionnels <span class=\"arabpsy-math-inline\" data-latex=\"p\">$p$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"q\">$q$<\/span> appartenant \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbb{R}^n\">$\\mathbb{R}^n$<\/span>, dont les composantes individuelles sont index\u00e9es de $1$ \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"n\">$n$<\/span> de telle sorte que <span class=\"arabpsy-math-inline\" data-latex=\"p = (p_1, p_2, dots, p_n)^T\">$p = (p_1, p_2, dots, p_n)^T$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"q = (q_1, q_2, dots, q_n)^T\">$q = (q_1, q_2, dots, q_n)^T$<\/span>. La distance euclidienne entre ces deux vecteurs, formellement assimil\u00e9e \u00e0 la norme <span class=\"arabpsy-math-inline\" data-latex=\"L_2\">$L_2$<\/span> de leur vecteur diff\u00e9rence, est d\u00e9finie par l&rsquo;op\u00e9rateur fonctionnel suivant :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"d(p, q) = |p - q|_2 = \\sqrt{\\sum_{i=1}^{n} (p_i - q_i)^2}\">$$d(p, q) = |p &#8211; q|_2 = \\sqrt{\\sum_{i=1}^{n} (p_i &#8211; q_i)^2}$$<\/span><\/p>\n<p>Cette formulation s&rsquo;inscrit au sein de la famille plus large des m\u00e9triques de Minkowski, dont la forme param\u00e9trique g\u00e9n\u00e9rale pour un ordre r\u00e9el <span class=\"arabpsy-math-inline\" data-latex=\"p ge 1\">$p ge 1$<\/span> s&rsquo;\u00e9nonce comme la racine <span class=\"arabpsy-math-inline\" data-latex=\"p\">$p$<\/span>-i\u00e8me de la somme des valeurs absolues des \u00e9carts \u00e9lev\u00e9s \u00e0 la puissance <span class=\"arabpsy-math-inline\" data-latex=\"p\">$p$<\/span>. Lorsque le param\u00e8tre d&rsquo;ordre est fix\u00e9 \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"p=1\">$p=1$<\/span>, la m\u00e9trique converge vers la distance de Manhattan (ou norme <span class=\"arabpsy-math-inline\" data-latex=\"L_1\">$L_1$<\/span>), qui contraint le d\u00e9placement le long d&rsquo;axes strictement orthogonaux \u00e0 la mani\u00e8re d&rsquo;un r\u00e9seau viaire orthogonal. \u00c0 l&rsquo;extr\u00eame oppos\u00e9, lorsque <span class=\"arabpsy-math-inline\" data-latex=\"p\">$p$<\/span> tend vers l&rsquo;infini positif (<span class=\"arabpsy-math-inline\" data-latex=\"p to \\infty\">$p to \\infty$<\/span>), la distance de Chebyshev (ou norme uniforme <span class=\"arabpsy-math-inline\" data-latex=\"L_\\infty\">$L_\\infty$<\/span>) ne retient que l&rsquo;\u00e9cart maximal absolu projet\u00e9 sur une unique dimension :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\lim_{p to \\infty} |p - q|_p = \\max_{1 le i le n} |p_i - q_i|\">$$\\lim_{p to \\infty} |p &#8211; q|_p = \\max_{1 le i le n} |p_i &#8211; q_i|$$<\/span><\/p>\n<p>La norme euclidienne <span class=\"arabpsy-math-inline\" data-latex=\"L_2\">$L_2$<\/span> occupe une place singuli\u00e8re au sein de cette taxinomie : elle est l&rsquo;unique m\u00e9trique de Minkowski induite par un produit scalaire canonique, conf\u00e9rant \u00e0 l&rsquo;espace une invariance g\u00e9om\u00e9trique sous l&rsquo;effet des transformations orthogonales, telles que les rotations et les r\u00e9flexions vectorielles.<\/p>\n<h3>1.3 Propri\u00e9t\u00e9s axiomatiques des m\u00e9triques de distance<\/h3>\n<p>Pour qu&rsquo;une fonctionnelle math\u00e9matique <span class=\"arabpsy-math-inline\" data-latex=\"d: \\mathbb{R}^n \\times \\mathbb{R}^n to \\mathbb{R}\">$d: \\mathbb{R}^n \\times \\mathbb{R}^n to \\mathbb{R}$<\/span> soit formellement qualifi\u00e9e de m\u00e9trique au sens de la topologie g\u00e9n\u00e9rale, elle doit satisfaire sans d\u00e9rogation \u00e0 un ensemble strict de quatre axiomes r\u00e9gissant les espaces m\u00e9triques. La distance euclidienne v\u00e9rifie rigoureusement ces conditions pour tous vecteurs <span class=\"arabpsy-math-inline\" data-latex=\"x, y, z in \\mathbb{R}^n\">$x, y, z in \\mathbb{R}^n$<\/span> :<\/p>\n<ul>\n<li><strong>Non-n\u00e9gativit\u00e9 :<\/strong> <span class=\"arabpsy-math-inline\" data-latex=\"d(x, y) ge 0\">$d(x, y) ge 0$<\/span>. La mesure d&rsquo;\u00e9cart spatial ne peut produire de valeur scalaire n\u00e9gative, refl\u00e9tant la nature physique d&rsquo;une magnitude.<\/li>\n<li><strong>Identit\u00e9 des indiscernables :<\/strong> <span class=\"arabpsy-math-inline\" data-latex=\"d(x, y) = 0 iff x = y\">$d(x, y) = 0 iff x = y$<\/span>. Deux points pr\u00e9sentent une distance nulle si et seulement si l&rsquo;int\u00e9gralit\u00e9 de leurs composantes respectives sont rigoureusement identiques dans l&rsquo;espace sous-jacent.<\/li>\n<li><strong>Sym\u00e9trie :<\/strong> <span class=\"arabpsy-math-inline\" data-latex=\"d(x, y) = d(y, x)\">$d(x, y) = d(y, x)$<\/span>. L&rsquo;\u00e9l\u00e9vation au carr\u00e9 des diff\u00e9rences scalaires annule l&rsquo;incidence de l&rsquo;ordre des op\u00e9randes : <span class=\"arabpsy-math-inline\" data-latex=\"(x_i - y_i)^2 = (-(y_i - x_i))^2 = (y_i - x_i)^2\">$(x_i &#8211; y_i)^2 = (-(y_i &#8211; x_i))^2 = (y_i &#8211; x_i)^2$<\/span>.<\/li>\n<li><strong>In\u00e9galit\u00e9 triangulaire :<\/strong> <span class=\"arabpsy-math-inline\" data-latex=\"d(x, z) le d(x, y) + d(y, z)\">$d(x, z) le d(x, y) + d(y, z)$<\/span>. Le trajet g\u00e9od\u00e9sique rectiligne reliant directement <span class=\"arabpsy-math-inline\" data-latex=\"x\">$x$<\/span> \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"z\">$z$<\/span> est syst\u00e9matiquement inf\u00e9rieur ou \u00e9gal \u00e0 tout trajet alternatif transitant par un sommet interm\u00e9diaire <span class=\"arabpsy-math-inline\" data-latex=\"y\">$y$<\/span>.<\/li>\n<\/ul>\n<p>La validation de l&rsquo;in\u00e9galit\u00e9 triangulaire pour la distance euclidienne repose sur l&rsquo;in\u00e9galit\u00e9 de Cauchy-Schwarz appliqu\u00e9e au produit scalaire canonique. Cette propri\u00e9t\u00e9 garantit la consistance topologique de l&rsquo;espace, interdisant l&rsquo;\u00e9mergence de paradoxes g\u00e9om\u00e9triques lors de la recherche de plus courts chemins ou de regroupements spatiaux.<\/p>\n<h2>2. Calcul de la distance euclidienne en Python pur sans d\u00e9pendances externes<\/h2>\n<h3>2.1 Impl\u00e9mentation algorithmique avec boucles it\u00e9ratives et le module math<\/h3>\n<p>L&rsquo;impl\u00e9mentation de la distance euclidienne \u00e0 partir des primitives fondamentales du langage Python, sans solliciter de biblioth\u00e8ques tierces, constitue une \u00e9tape p\u00e9dagogique essentielle pour appr\u00e9hender la d\u00e9composition proc\u00e9durale du calcul. Dans cette perspective, la fonction native du module standard <a rel=\"noopener noreferrer\" href=\"https:\/\/docs.python.org\/3\/library\/math.html\">math.sqrt<\/a> est mobilis\u00e9e afin de calculer la racine carr\u00e9e de l&rsquo;accumulateur arithm\u00e9tique. Cette d\u00e9marche n\u00e9cessite au pr\u00e9alable de valider la conformit\u00e9 des structures de donn\u00e9es en entr\u00e9e, en v\u00e9rifiant imp\u00e9rativement que les listes de coordonn\u00e9es poss\u00e8dent des longueurs identiques afin de pr\u00e9venir toute erreur de d\u00e9synchronisation d&rsquo;index.<\/p>\n<p>Le d\u00e9veloppement d&rsquo;une fonction Python robuste et r\u00e9utilisable pour des vecteurs \u00e0 une dimension s&rsquo;articule autour d&rsquo;une boucle imp\u00e9rative conventionnelle :<\/p>\n<pre><code>import math\n\ndef distance_euclidienne_imperative(vecteur_a, vecteur_b):\n    if len(vecteur_a) != len(vecteur_b):\n        raise ValueError(\"Les vecteurs doivent presenter une dimensionnalite identique.\")\n    \n    somme_quadratique = 0.0\n    for i in range(len(vecteur_a)):\n        ecart = vecteur_a[i] - vecteur_b[i]\n        somme_quadratique += ecart * ecart\n        \n    return math.sqrt(somme_quadratique)\n<\/code><\/pre>\n<p>Cette approche permet d&rsquo;observer directement le m\u00e9canisme d&rsquo;accumulation arithm\u00e9tique \u00e9l\u00e9ment par \u00e9l\u00e9ment. L&rsquo;utilisation de la multiplication directe <code>ecart * ecart<\/code> est ici privil\u00e9gi\u00e9e par rapport \u00e0 l&rsquo;op\u00e9rateur de puissance <code>ecart ** 2<\/code>, car elle s&rsquo;av\u00e8re substantiellement plus rapide au sein de l&rsquo;interpr\u00e9teur CPython en \u00e9vitant l&rsquo;appel aux routines g\u00e9n\u00e9riques de gestion des exposants en virgule flottante.<\/p>\n<h3>2.2 Approche fonctionnelle avec compr\u00e9hensions de listes et zip()<\/h3>\n<p>Le paradigme de programmation fonctionnelle disponible en Python permet de condenser l&rsquo;architecture algorithmique pr\u00e9c\u00e9dente tout en \u00e9levant son niveau d&rsquo;abstraction s\u00e9mantique. L&rsquo;association de la fonction sommatoire int\u00e9gr\u00e9e <code>sum()<\/code>, de la fonction de maillage parall\u00e8le <code>zip()<\/code> et d&rsquo;une expression g\u00e9n\u00e9ratrice permet de s&rsquo;affranchir de la gestion manuelle des index num\u00e9riques, source r\u00e9currente d&rsquo;erreurs logiques de type d\u00e9passement d&rsquo;indice.<\/p>\n<pre><code>import math\n\ndef distance_euclidienne_fonctionnelle(vecteur_a, vecteur_b):\n    if len(vecteur_a) != len(vecteur_b):\n        raise ValueError(\"Les vecteurs doivent presenter une dimensionnalite identique.\")\n    \n    return math.sqrt(sum((a - b) ** 2 for a, b in zip(vecteur_a, vecteur_b)))\n<\/code><\/pre>\n<p>L&rsquo;utilisation d&rsquo;une expression g\u00e9n\u00e9ratrice au lieu d&rsquo;une compr\u00e9hension de liste stricte entre crochets pr\u00e9sente l&rsquo;avantage de ne pas mat\u00e9rialiser en m\u00e9moire l&rsquo;int\u00e9gralit\u00e9 des diff\u00e9rences quadratiques sous forme de liste interm\u00e9diaire temporaire. Les termes sont \u00e9valu\u00e9s \u00e0 la vol\u00e9e et consomm\u00e9s imm\u00e9diatement par la primitive <code>sum()<\/code>, optimisant ainsi l&#8217;empreinte r\u00e9sidente. En accord avec les recommandations stylistiques de la <a rel=\"noopener noreferrer\" href=\"https:\/\/peps.python.org\/pep-0008\/\">PEP 8<\/a>, cette \u00e9criture conf\u00e8re au code une compacit\u00e9 expressive proche de l&rsquo;\u00e9criture formelle math\u00e9matique.<\/p>\n<h3>2.3 Exploitation de math.dist() introduite dans Python 3.8<\/h3>\n<p>Conscient de la r\u00e9currence de ce calcul au sein des scripts scientifiques et applicatifs, le comit\u00e9 de d\u00e9veloppement de Python a introduit, \u00e0 compter de la version 3.8, la fonction native <code>math.dist()<\/code>. Cette fonction standardise le calcul de la distance euclidienne entre deux it\u00e9rables de coordonn\u00e9es de m\u00eame longueur sous une signature syntaxique particuli\u00e8rement sobre :<\/p>\n<pre><code>import math\n\npoint_alpha = [1.5, 3.2, -4.8, 7.0]\npoint_beta = [2.8, -0.4, -1.2, 5.5]\n\ndistance_calculee = math.dist(point_alpha, point_beta)\n<\/code><\/pre>\n<p>L&rsquo;avantage pr\u00e9pond\u00e9rant de <code>math.dist()<\/code> r\u00e9side dans son impl\u00e9mentation sous-jacente cod\u00e9e int\u00e9gralement en langage C au c\u0153ur du moteur CPython. Cette routine convertit les it\u00e9rables Python directement en tableaux natifs de structures <code>double<\/code> et effectue la sommation quadratique sans solliciter l&rsquo;interpr\u00e9teur d&rsquo;\u00e9valuation des <em>bytecodes<\/em> \u00e0 chaque incr\u00e9ment de boucle. Par ailleurs, <code>math.dist()<\/code> prend en charge nativement la d\u00e9tection des disparit\u00e9s de taille entre s\u00e9quences en levant imm\u00e9diatement une exception <code>ValueError<\/code>, tout en assurant une compensation num\u00e9rique accrue contre les erreurs d&rsquo;arrondi selon les sp\u00e9cifications rigoureuses de la norme IEEE 754.<\/p>\n<h3>2.4 Analyse de complexit\u00e9 temporelle et spatiale du code pur<\/h3>\n<p>L&rsquo;\u00e9valuation des performances algorithmiques du code en Python pur s&rsquo;\u00e9tudie sous l&rsquo;angle de la th\u00e9orie de la complexit\u00e9 computationnelle. Soit <span class=\"arabpsy-math-inline\" data-latex=\"n\">$n$<\/span> le nombre d&rsquo;\u00e9l\u00e9ments scalaires constituant les vecteurs mis en correspondance (la dimension spatiale) :<\/p>\n<ul>\n<li><strong>Complexit\u00e9 temporelle :<\/strong> L&rsquo;analyse de l&rsquo;algorithme met en \u00e9vidence une relation strictement lin\u00e9aire, not\u00e9e <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(n)\">$\\mathcal{O}(n)$<\/span>. Chaque dimension doit obligatoirement \u00eatre consult\u00e9e, soustraite, \u00e9lev\u00e9e au carr\u00e9 puis ajout\u00e9e au registre d&rsquo;accumulation. Aucune op\u00e9ration de court-circuit n&rsquo;\u00e9tant permise pour le calcul exact, la borne asymptotique inf\u00e9rieure et la borne sup\u00e9rieure co\u00efncident en <span class=\"arabpsy-math-inline\" data-latex=\"Theta(n)\">$Theta(n)$<\/span>.<\/li>\n<li><strong>Complexit\u00e9 spatiale :<\/strong> Pour l&rsquo;approche imp\u00e9rative et la variante g\u00e9n\u00e9ratrice exploitant <code>math.dist()<\/code>, la m\u00e9moire auxiliaire allou\u00e9e demeure constante, soit <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(1)\">$\\mathcal{O}(1)$<\/span>, car seul un nombre fixe de variables d&rsquo;\u00e9tat (accumulateur et index) est maintenu en pile. En revanche, l&rsquo;instanciation imprudente d&rsquo;une compr\u00e9hension de liste compl\u00e8te <code>[(a - b)**2 for a, b in zip(...)]<\/code> r\u00e9clame une allocation auxiliaire de complexit\u00e9 lin\u00e9aire <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(n)\">$\\mathcal{O}(n)$<\/span>.<\/li>\n<\/ul>\n<p>N\u00e9anmoins, la structure sous-jacente des listes Python induit une surcharge m\u00e9moire importante : chaque \u00e9l\u00e9ment d&rsquo;une liste standard est en r\u00e9alit\u00e9 un pointeur vers un objet boxing <code>PyObject<\/code> allou\u00e9 de mani\u00e8re discontinue sur le tas (heap). Cette discontinuit\u00e9 spatiale brise la localit\u00e9 de r\u00e9f\u00e9rence du cache du processeur, g\u00e9n\u00e9rant des d\u00e9fauts de cache (<em>cache misses<\/em>) r\u00e9currents lors du parcours s\u00e9quentiel, ce qui handicape lourdement les it\u00e9rations pures sur des vecteurs massifs.<\/p>\n<h2>3. Calcul vectoris\u00e9 standard avec NumPy : numpy.linalg.norm<\/h2>\n<h3>3.1 D\u00e9finition de structures vectorielles avec np.array<\/h3>\n<p>Pour d\u00e9passer les limitations architecturales inh\u00e9rentes \u00e0 l&rsquo;interpr\u00e9teur CPython, la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/\">NumPy<\/a> constitue la fondation de l&rsquo;\u00e9cosyst\u00e8me num\u00e9rique haute performance. NumPy substitue aux listes cha\u00een\u00e9es de pointeurs g\u00e9n\u00e9riques la structure de donn\u00e9es <code>ndarray<\/code> (tableau \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> dimensions). Un <code>ndarray<\/code> se compose d&rsquo;un bloc de m\u00e9moire contigu, allou\u00e9 lin\u00e9airement, o\u00f9 tous les \u00e9l\u00e9ments partagent strictement le m\u00eame type primitif sous-jacent (par exemple, des nombres \u00e0 virgule flottante double pr\u00e9cision de 64 bits).<\/p>\n<pre><code>import numpy as np\n\npoint_u = np.array([1.2, 5.6, -3.4, 8.9], dtype=np.float64)\npoint_v = np.array([4.1, 2.3, 0.5, 6.1], dtype=np.float64)\n<\/code><\/pre>\n<p>Cette structure conf\u00e8re deux avantages mat\u00e9riels d\u00e9cisifs : un acc\u00e8s imm\u00e9diat aux adresses m\u00e9moires par simple calcul d&rsquo;arithm\u00e9tique de pointeurs \u00e0 partir du pas d&rsquo;avancement (<em>stride<\/em>), et la capacit\u00e9 d&rsquo;acheminer les donn\u00e9es directement dans les registres SIMD (<em>Single Instruction, Multiple Data<\/em>) des processeurs contemporains (tels que les architectures AVX-2 ou AVX-512). La conversion de conteneurs standards vers des tableaux NumPy homogen\u00e9ise les donn\u00e9es et supprime la surcharge dynamique de v\u00e9rification de type propre aux objets Python.<\/p>\n<h3>3.2 Application de la fonction numpy.linalg.norm<\/h3>\n<p>Le module d&rsquo;alg\u00e8bre lin\u00e9aire de NumPy encapsule des appels hautement optimis\u00e9s vers des biblioth\u00e8ques compil\u00e9es de bas niveau (<a rel=\"noopener noreferrer\" href=\"https:\/\/www.netlib.org\/lapack\/\">LAPACK<\/a> et <a rel=\"noopener noreferrer\" href=\"https:\/\/www.netlib.org\/blas\/\">BLAS<\/a>). La fonction <code>numpy.linalg.norm<\/code> fournit une abstraction g\u00e9n\u00e9rique permettant de quantifier la norme vectorielle d&rsquo;une structure de tenseurs. Dans sa configuration par d\u00e9faut ou en sp\u00e9cifiant l&rsquo;argument d&rsquo;ordre <code>ord=2<\/code>, cette fonction r\u00e9sout exactement la norme euclidienne du vecteur r\u00e9sultant de la soustraction vectoris\u00e9e des deux points :<\/p>\n<pre><code>import numpy as np\n\ndistance_norm = np.linalg.norm(point_u - point_v, ord=2)\n<\/code><\/pre>\n<p>L&rsquo;op\u00e9ration <code>point_u - point_v<\/code> s&rsquo;ex\u00e9cute enti\u00e8rement au sein des couches C compil\u00e9es de NumPy sous forme d&rsquo;op\u00e9ration vectorielle \u00e9l\u00e9ment par \u00e9l\u00e9ment. Le vecteur de diff\u00e9rences en r\u00e9sultant est ensuite trait\u00e9 par <code>norm<\/code>, qui applique une strat\u00e9gie de sommation quadratique pond\u00e9r\u00e9e destin\u00e9e \u00e0 juguler les d\u00e9faillances num\u00e9riques telles que les d\u00e9passements de capacit\u00e9 vers le haut (<em>overflow<\/em>) ou vers le bas (<em>underflow<\/em>), garantissant une pr\u00e9cision sup\u00e9rieure lors de manipulations de grandeurs scalaires extr\u00eames.<\/p>\n<h3>3.3 D\u00e9composition alg\u00e9brique avec np.sqrt et np.sum<\/h3>\n<p>Bien que <code>np.linalg.norm<\/code> offre une abstraction formelle universelle, il demeure fr\u00e9quent d&rsquo;impl\u00e9menter la d\u00e9composition alg\u00e9brique explicite de la distance euclidienne en mobilisant les fonctions universelles (<em>ufuncs<\/em>) <code>np.sum<\/code> et <code>np.sqrt<\/code>. Cette m\u00e9thode manuelle contourne la logique de v\u00e9rification g\u00e9n\u00e9raliste de la fonction d&rsquo;alg\u00e8bre lin\u00e9aire et se r\u00e9v\u00e8le fr\u00e9quemment plus v\u00e9loce pour des calculs unidimensionnels r\u00e9currents :<\/p>\n<pre><code>import numpy as np\n\ndifference = point_u - point_v\ndistance_decomp = np.sqrt(np.sum(difference ** 2))\n<\/code><\/pre>\n<p>Pour raffiner l&rsquo;efficacit\u00e9 d&rsquo;ex\u00e9cution de cette instruction, l&rsquo;expression <code>difference ** 2<\/code> peut \u00eatre remplac\u00e9e avantageusement par l&rsquo;op\u00e9ration de produit scalaire vectoris\u00e9 <code>np.dot(difference, difference)<\/code>. En effet, l&rsquo;\u00e9l\u00e9vation au carr\u00e9 requiert l&rsquo;application d&rsquo;un op\u00e9rateur de puissance sur chaque entr\u00e9e, tandis que le produit scalaire utilise directement la routine g\u00e9om\u00e9trique BLAS de niveau 1 (<code>ddot<\/code>), fusionnant les op\u00e9rations de multiplication et de sommation au sein d&rsquo;une boucle vectorielle unique et \u00e9vitant une allocation temporaire pour le tableau au carr\u00e9 :<\/p>\n<pre><code>distance_dot = np.sqrt(np.dot(difference, difference))\n<\/code><\/pre>\n<h3>3.4 Gestion rigoureuse des erreurs de dimension et ValueError<\/h3>\n<p>Une rigueur algorithmique absolue impose de g\u00e9rer les disjonctions dimensionnelles susceptibles d&rsquo;intervenir lors de l&rsquo;ingestion de donn\u00e9es d\u00e9grad\u00e9es. Si deux tableaux NumPy n&rsquo;exhibent pas des topologies g\u00e9om\u00e9triques conformes, le moteur interne de NumPy tente d&rsquo;appliquer les r\u00e8gles de diffusion dimensionnelle (<em>broadcasting<\/em>). Si ces formes s&rsquo;av\u00e8rent structurellement incompatibles pour un alignement \u00e9l\u00e9ment par \u00e9l\u00e9ment, une exception de type <code>ValueError<\/code> est imm\u00e9diatement lev\u00e9e par la machine virtuelle :<\/p>\n<pre><code>import numpy as np\n\npoint_err_1 = np.array([1.0, 2.0, 3.0])\npoint_err_2 = np.array([1.0, 2.0])\n\ntry:\n    distance_invalide = np.linalg.norm(point_err_1 - point_err_2)\nexcept ValueError as err:\n    print(f\"Echec de broadcast vectoriel : {err}\")\n<\/code><\/pre>\n<p>Dans les pipelines de traitement industriels, il convient d&rsquo;anticiper ces d\u00e9faillances de transmission par des assertions formelles ou des blocs conditionnels fond\u00e9s sur l&rsquo;attribut <code>array.shape<\/code>, validant pr\u00e9alablement que <code>point_u.shape == point_v.shape<\/code>. Cette proactivit\u00e9 programmatique pr\u00e9vient les dysfonctionnements silencieux li\u00e9s \u00e0 des diffusions non souhait\u00e9es de tenseurs, assurant ainsi la robustesse d\u00e9terministe des calculs scientifiques automatis\u00e9s.<\/p>\n<h2>4. Broadcasting NumPy et calculs multidimensionnels par matrices<\/h2>\n<h3>4.1 Distance euclidienne entre un point de r\u00e9f\u00e9rence et une matrice<\/h3>\n<p>L&rsquo;un des paradigmes les plus puissants de NumPy r\u00e9side dans le m\u00e9canisme de <strong>broadcasting<\/strong> (diffusion automatique des dimensions). Ce protocole permet d&rsquo;ex\u00e9cuter des op\u00e9rations arithm\u00e9tiques binaires entre des tableaux poss\u00e9dant des g\u00e9om\u00e9tries de dimensions divergentes mais compatibles, sans duplication superflue de la m\u00e9moire vive. Consid\u00e9rons la probl\u00e9matique r\u00e9currente consistant \u00e0 d\u00e9terminer la distance euclidienne s\u00e9parant un vecteur unique de r\u00e9f\u00e9rence <span class=\"arabpsy-math-inline\" data-latex=\"v in \\mathbb{R}^d\">$v in \\mathbb{R}^d$<\/span> d&rsquo;un corpus matriciel complet <span class=\"arabpsy-math-inline\" data-latex=\"M in \\mathbb{R}^{N \\times d}\">$M in \\mathbb{R}^{N \\times d}$<\/span> contenant <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> observations \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"d\">$d$<\/span> dimensions :<\/p>\n<pre><code>import numpy as np\n\ncentroide = np.array([2.5, 4.0, -1.0])\nmatrice_observations = np.array([\n    [1.0, 2.0, -0.5],\n    [3.0, 5.0, -2.0],\n    [0.5, 1.5, 3.0],\n    [2.5, 4.0, -1.0]\n])\n\ndifferences = matrice_observations - centroide\ndistances = np.linalg.norm(differences, axis=1)\n<\/code><\/pre>\n<p>Dans cet exemple, le vecteur <code>centroide<\/code>, dont la signature est initialement de forme <code>(3,)<\/code>, est virtuellement \u00e9tir\u00e9 le long de l&rsquo;axe vertical pour co\u00efncider avec la morphologie <code>(4, 3)<\/code> de la matrice h\u00f4te. La soustraction s&rsquo;op\u00e8re sur chaque ligne de mani\u00e8re instantan\u00e9e au niveau du moteur C. L&rsquo;invocation subs\u00e9quente de <code>np.linalg.norm(..., axis=1)<\/code> sp\u00e9cifie formellement que la r\u00e9duction quadratique doit s&rsquo;ex\u00e9cuter le long des colonnes pour chaque ligne individuellement, d\u00e9livrant un vecteur unidimensionnel de dimension <span class=\"arabpsy-math-inline\" data-latex=\"N=4\">$N=4$<\/span> mat\u00e9rialisant l&rsquo;ensemble des \u00e9carts scalaires vis-\u00e0-vis du centro\u00efde.<\/p>\n<h3>4.2 Calcul de matrices de distances par paires (pairwise distance)<\/h3>\n<p>Lorsque l&rsquo;on doit \u00e9valuer de mani\u00e8re exhaustive l&rsquo;ensemble des distances reliant deux ensembles matriciels distincts, not\u00e9s respectivement <span class=\"arabpsy-math-inline\" data-latex=\"A in \\mathbb{R}^{N \\times d}\">$A in \\mathbb{R}^{N \\times d}$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"B in \\mathbb{R}^{M \\times d}\">$B in \\mathbb{R}^{M \\times d}$<\/span>, l&rsquo;ing\u00e9nierie vectorielle sollicite l&rsquo;expansion tensorielle via la constante d&rsquo;indexation <code>np.newaxis<\/code> (\u00e9quivalente \u00e0 <code>None<\/code>). Cette technique introduit artificiellement des axes unitaires pour contraindre le broadcasting bilat\u00e9ral dans un espace tridimensionnel :<\/p>\n<pre><code>import numpy as np\n\nmatrice_a = np.random.rand(100, 5)\nmatrice_b = np.random.rand(50, 5)\n\n# matrice_a[:, np.newaxis, :] adopte la forme (100, 1, 5)\n# matrice_b[np.newaxis, :, :] adopte la forme (1, 50, 5)\ndiff_tenseur = matrice_a[:, np.newaxis, :] - matrice_b[np.newaxis, :, :]\n\nmatrice_distances_paires = np.sqrt(np.sum(diff_tenseur ** 2, axis=-1))\n<\/code><\/pre>\n<p>Le tenseur r\u00e9sultant de la soustraction interm\u00e9diaire adopte la forme g\u00e9om\u00e9trique <code>(100, 50, 5)<\/code>. L&rsquo;op\u00e9rateur <code>np.sum<\/code> r\u00e9duit ensuite la somme quadratique le long du dernier axe dimensionnel (<code>axis=-1<\/code>), produisant une matrice finale de forme <code>(100, 50)<\/code> o\u00f9 chaque cellule d&rsquo;indice <span class=\"arabpsy-math-inline\" data-latex=\"(i, j)\">$(i, j)$<\/span> traduit sans ambigu\u00eft\u00e9 la distance euclidienne s\u00e9parant la <span class=\"arabpsy-math-inline\" data-latex=\"i\">$i$<\/span>-i\u00e8me observation de <span class=\"arabpsy-math-inline\" data-latex=\"A\">$A$<\/span> de la <span class=\"arabpsy-math-inline\" data-latex=\"j\">$j$<\/span>-i\u00e8me observation de <span class=\"arabpsy-math-inline\" data-latex=\"B\">$B$<\/span>. Cette approche \u00e9limine toute boucle explicite dans l&rsquo;espace utilisateur, maximisant l&rsquo;utilisation des unit\u00e9s d&rsquo;ex\u00e9cution mat\u00e9rielles.<\/p>\n<h3>4.3 Optimisation de l&#8217;empreinte m\u00e9moire pour les matrices denses<\/h3>\n<p>Nonobstant son \u00e9l\u00e9gance math\u00e9matique, la m\u00e9thode par expansion dimensionnelle <code>np.newaxis<\/code> exhibe une vuln\u00e9rabilit\u00e9 critique : elle impose la mat\u00e9rialisation d&rsquo;un tenseur interm\u00e9diaire de dimension <span class=\"arabpsy-math-inline\" data-latex=\"N \\times M \\times d\">$N \\times M \\times d$<\/span>. D\u00e8s lors que <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"M\">$M$<\/span> atteignent des ordres de grandeur de plusieurs dizaines de milliers d&rsquo;unit\u00e9s, la quantit\u00e9 de m\u00e9moire vive n\u00e9cessaire outrepasse instantan\u00e9ment la capacit\u00e9 mat\u00e9rielle, d\u00e9clenchant une lev\u00e9e d&rsquo;erreur <code>MemoryError<\/code>. Pour juguler ce goulet d&rsquo;\u00e9tranglement, on recourt \u00e0 l&rsquo;expansion polynomiale du carr\u00e9 euclidien :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"|a_i - b_j|^2 = |a_i|^2 - 2 \\langle a_i, b_j \\rangle + |b_j|^2\">$$|a_i &#8211; b_j|^2 = |a_i|^2 &#8211; 2 \\langle a_i, b_j \\rangle + |b_j|^2$$<\/span><\/p>\n<p>Cette d\u00e9composition alg\u00e9brique permet de reformuler int\u00e9gralement le calcul matriciel sous forme de multiplications matricielles directes (<a rel=\"noopener noreferrer\" href=\"https:\/\/mathworld.wolfram.com\/MatrixMultiplication.html\">GEMM<\/a>) g\u00e9r\u00e9es par les routines BLAS :<\/p>\n<pre><code>import numpy as np\n\ndef pairwise_euclidean_optimisee(X, Y):\n    norme_carree_x = np.sum(X ** 2, axis=1)[:, np.newaxis]\n    norme_carree_y = np.sum(Y ** 2, axis=1)[np.newaxis, :]\n    produit_croise = np.dot(X, Y.T)\n    \n    distance_carree = norme_carree_x - 2.0 * produit_croise + norme_carree_y\n    \n    # Nettoyage des imprecisions numeriques pouvant generer de legeres valeurs negatives\n    distance_carree = np.maximum(distance_carree, 0.0)\n    return np.sqrt(distance_carree)\n<\/code><\/pre>\n<p>Cette architecture r\u00e9duit l&#8217;empreinte m\u00e9moire \u00e0 l&rsquo;allocation stricte de la matrice finale de r\u00e9sultat <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N \\times M)\">$\\mathcal{O}(N \\times M)$<\/span>, contournant int\u00e9gralement la cr\u00e9ation du tenseur <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N \\times M \\times d)\">$\\mathcal{O}(N \\times M \\times d)$<\/span>, tout en capitalisant sur l&rsquo;extr\u00eame optimisation multicoeur des primitives <code>np.dot<\/code>.<\/p>\n<h2>5. Calculs avanc\u00e9s et sp\u00e9cialis\u00e9s avec le module SciPy<\/h2>\n<h3>5.1 Utilisation de scipy.spatial.distance.euclidean<\/h3>\n<p>La biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/scipy.org\/\">SciPy<\/a> h\u00e9berge dans son sous-module d&rsquo;analyse spatiale <code>scipy.spatial.distance<\/code> des routines sp\u00e9cialement con\u00e7ues pour le calcul m\u00e9trique sur des structures de donn\u00e9es g\u00e9om\u00e9triques. La fonction <code>euclidean<\/code> constitue l&rsquo;homologue d\u00e9di\u00e9 de la norme euclidienne pour les vecteurs unidimensionnels :<\/p>\n<pre><code>from scipy.spatial.distance import euclidean\n\npoint_x = [0.0, 1.0, 2.0, 3.0]\npoint_y = [4.0, 3.0, 2.0, 1.0]\n\ndistance_mesuree = euclidean(point_x, point_y)\n<\/code><\/pre>\n<p>L&rsquo;utilit\u00e9 principale de <code>scipy.spatial.distance.euclidean<\/code> r\u00e9side dans sa capacit\u00e9 \u00e0 traiter de mani\u00e8re transparente des entr\u00e9es h\u00e9t\u00e9rog\u00e8nes (listes natives, tuples, tableaux NumPy) en les convertissant automatiquement en tableaux num\u00e9riques sans n\u00e9cessiter d&rsquo;intervention manuelle du programmeur. En outre, le module int\u00e8gre des contr\u00f4les internes stricts validant l&rsquo;absence de composantes complexes et imposant la validit\u00e9 arithm\u00e9tique des arguments selon les conventions math\u00e9matiques rigoureuses du calcul scientifique.<\/p>\n<h3>5.2 G\u00e9n\u00e9ration de matrices compactes avec scipy.spatial.distance.pdist<\/h3>\n<p>Lors de l&rsquo;analyse d&rsquo;un nuage de points unique <span class=\"arabpsy-math-inline\" data-latex=\"X in \\mathbb{R}^{N \\times d}\">$X in \\mathbb{R}^{N \\times d}$<\/span>, la matrice compl\u00e8te des distances d&rsquo;ordre <span class=\"arabpsy-math-inline\" data-latex=\"N \\times N\">$N \\times N$<\/span> s&rsquo;av\u00e8re intrins\u00e8quement redondante. D&rsquo;une part, la diagonale principale est identiquement nulle (<span class=\"arabpsy-math-inline\" data-latex=\"d(x_i, x_i) = 0\">$d(x_i, x_i) = 0$<\/span>). D&rsquo;autre part, la propri\u00e9t\u00e9 de sym\u00e9trie (<span class=\"arabpsy-math-inline\" data-latex=\"d(x_i, x_j) = d(x_j, x_i)\">$d(x_i, x_j) = d(x_j, x_i)$<\/span>) implique que le triangle inf\u00e9rieur constitue le miroir strict du triangle sup\u00e9rieur. Pour \u00e9viter de doubler inutilement la consommation de m\u00e9moire vive, la fonction <code>scipy.spatial.distance.pdist<\/code> calcule uniquement les paires non redondantes et renvoie une matrice condens\u00e9e sous la forme d&rsquo;un vecteur plat 1D de dimension <span class=\"arabpsy-math-inline\" data-latex=\"\\frac{N(N-1)}{2}\">$\\frac{N(N-1)}{2}$<\/span> :<\/p>\n<pre><code>import numpy as np\nfrom scipy.spatial.distance import pdist, squareform\n\njeu_donnees = np.random.normal(loc=0.0, scale=1.0, size=(1000, 10))\n\n# Calcul de la matrice sous forme condensee (triangulaire superieure)\ndistances_condensees = pdist(jeu_donnees, metric='euclidean')\n\n# Expansion optionnelle vers la matrice carree sym\u00e9trique complete\nmatrice_symetrique = squareform(distances_condensees)\n<\/code><\/pre>\n<p>Cette approche compacte engendre une \u00e9conomie m\u00e9moire de plus de 50 % par rapport \u00e0 la repr\u00e9sentation carr\u00e9e. L&rsquo;utilitaire auxiliaire <code>squareform<\/code> permet de transmuter bidirectionnellement la structure compress\u00e9e en une matrice carr\u00e9e classique, facilitant son int\u00e9gration dans des algorithmes n\u00e9cessitant un adressage indiciel bivari\u00e9.<\/p>\n<h3>5.3 Calculs inter-ensembles rapides avec scipy.spatial.distance.cdist<\/h3>\n<p>Pour mesurer les proximit\u00e9s entre deux ensembles g\u00e9om\u00e9triques disjoints sans avoir recours \u00e0 la programmation manuelle du broadcasting NumPy, la fonction <code>scipy.spatial.distance.cdist<\/code> offre l&rsquo;interface la plus rapide et la plus stable de l&rsquo;\u00e9cosyst\u00e8me Python :<\/p>\n<pre><code>import numpy as np\nfrom scipy.spatial.distance import cdist\n\ncollection_source = np.random.uniform(-5.0, 5.0, size=(500, 8))\ncollection_cible = np.random.uniform(-5.0, 5.0, size=(200, 8))\n\nmatrice_cdist = cdist(collection_source, collection_cible, metric='euclidean')\n<\/code><\/pre>\n<p>La fonction <code>cdist<\/code> d\u00e9l\u00e8gue l&rsquo;int\u00e9gralit\u00e9 du calcul \u00e0 des moteurs C pr\u00e9compil\u00e9s et optimis\u00e9s qui adaptent dynamiquement leurs boucles de parcours en fonction du volume dimensionnel et de la taille des ensembles afin de maximiser l&rsquo;usage du cache L1 et L2 du microprocesseur. En outre, la param\u00e9trisation textuelle de l&rsquo;argument <code>metric<\/code> permet d&rsquo;interchanger instantan\u00e9ment la distance euclidienne avec d&rsquo;autres m\u00e9triques (telles que <code>'cityblock'<\/code>, <code>'minkowski'<\/code> ou <code>'mahalanobis'<\/code>), conf\u00e9rant une grande flexibilit\u00e9 architecturale aux cha\u00eenes d&rsquo;analyse g\u00e9om\u00e9trique.<\/p>\n<h2>6. Calculs de distance euclidienne au sein de l&rsquo;\u00e9cosyst\u00e8me Pandas<\/h2>\n<h3>6.1 Distance euclidienne entre colonnes distinctes d&rsquo;un DataFrame<\/h3>\n<p>Dans le domaine de l&rsquo;ing\u00e9nierie des caract\u00e9ristiques (<em>feature engineering<\/em>) sous la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/\">Pandas<\/a>, le calcul de la distance euclidienne intervient fr\u00e9quemment pour quantifier l&rsquo;\u00e9cart spatial entre deux trajectoires ou deux mesures g\u00e9ographiques enregistr\u00e9es dans des colonnes synchronis\u00e9es au sein d&rsquo;un m\u00eame <code>DataFrame<\/code> :<\/p>\n<pre><code>import pandas as pd\nimport numpy as np\n\ndonnees_trajectoire = pd.DataFrame({\n    'debut_axe_x': [10.2, 14.5, 19.8, 25.1],\n    'debut_axe_y': [2.1, 4.3, 8.7, 12.0],\n    'fin_axe_x': [12.2, 17.5, 23.8, 29.1],\n    'fin_axe_y': [5.1, 8.3, 11.7, 16.0]\n})\n\n# Formulation vectorisee exploitant l'alignement des series Pandas\ndonnees_trajectoire['distance_deplacement'] = np.sqrt(\n    (donnees_trajectoire['fin_axe_x'] - donnees_trajectoire['debut_axe_x']) ** 2 +\n    (donnees_trajectoire['fin_axe_y'] - donnees_trajectoire['debut_axe_y']) ** 2\n)\n<\/code><\/pre>\n<p>Dans ce sc\u00e9nario, les s\u00e9ries temporelles ou spatiales sous forme d&rsquo;objets <code>pd.Series<\/code> exploitent directement les op\u00e9rateurs arithm\u00e9tiques vectoris\u00e9s de NumPy. L&rsquo;\u00e9valuation s&rsquo;ex\u00e9cute de mani\u00e8re align\u00e9e selon les index du <code>DataFrame<\/code>, sans g\u00e9n\u00e9rer de boucle Python explicite, et peuple une nouvelle s\u00e9rie scalaire repr\u00e9sentant la distance mesur\u00e9e pour chaque \u00e9v\u00e9nement.<\/p>\n<h3>6.2 Mesure de dissimilarit\u00e9 entre observations (lignes) cons\u00e9cutives ou cibl\u00e9es<\/h3>\n<p>Il est courant d&rsquo;analyser la d\u00e9rive temporelle ou la dissimilarit\u00e9 comportementale entre des \u00e9tats successifs d&rsquo;un syst\u00e8me. Cette t\u00e2che peut \u00eatre r\u00e9solue \u00e9l\u00e9gamment en articulant la m\u00e9thode <code>diff()<\/code> de Pandas avec les primitives de calcul m\u00e9trique :<\/p>\n<pre><code>import pandas as pd\nimport numpy as np\n\ntelemetrie = pd.DataFrame({\n    'capteur_1': [100.1, 101.3, 102.8, 102.1],\n    'capteur_2': [45.0, 46.2, 44.8, 43.9],\n    'capteur_3': [12.4, 12.8, 13.5, 14.1]\n})\n\n# Calcul des variations differentielles entre observations successives\ndeltas = telemetrie.diff().dropna()\ndistances_temporelles = np.sqrt(np.sum(deltas ** 2, axis=1))\n<\/code><\/pre>\n<p>Pour mesurer la distance entre deux individus ou \u00e9tats cibl\u00e9s non cons\u00e9cutifs, l&rsquo;op\u00e9rateur d&rsquo;indexation <code>iloc<\/code> permet d&rsquo;isoler les vecteurs d&rsquo;int\u00e9r\u00eat sous forme de s\u00e9ries avant de proc\u00e9der \u00e0 l&rsquo;\u00e9valuation g\u00e9om\u00e9trique :<\/p>\n<pre><code>sujet_alpha = telemetrie.iloc[0]\nsujet_beta = telemetrie.iloc[2]\ndistance_individus = np.linalg.norm(sujet_alpha - sujet_beta)\n<\/code><\/pre>\n<h3>6.3 Optimisation des performances : vectorisation versus m\u00e9thode apply<\/h3>\n<p>Une erreur fr\u00e9quente observ\u00e9e dans le code de traitement de donn\u00e9es sous Pandas consiste \u00e0 recourir \u00e0 la m\u00e9thode <code>DataFrame.apply()<\/code> avec l&rsquo;argument <code>axis=1<\/code> pour it\u00e9rer sur les rang\u00e9es :<\/p>\n<pre><code># Approche anti-pattern proscrite sur les volumetries substantielles\ndistance_lente = telemetrie.apply(\n    lambda ligne: np.linalg.norm(ligne[['capteur_1', 'capteur_2', 'capteur_3']]), \n    axis=1\n)\n<\/code><\/pre>\n<p>L&rsquo;utilisation de <code>apply(..., axis=1)<\/code> contraint Pandas \u00e0 instancier un objet <code>pd.Series<\/code> distinct pour chaque ligne du jeu de donn\u00e9es, introduisant une surcharge d&rsquo;allocation massive et d\u00e9truisant toute possibilit\u00e9 d&rsquo;acc\u00e9l\u00e9ration mat\u00e9rielle. Pour mesurer rigoureusement l&rsquo;impact de ce choix d&rsquo;impl\u00e9mentation, consid\u00e9rons une comparaison de performance sur un jeu de donn\u00e9es de 50 000 enregistrements :<\/p>\n<pre><code>import pandas as pd\nimport numpy as np\n\n# Generation d'un jeu de donnees dense\ndonnees_massives = pd.DataFrame(\n    np.random.randn(50000, 4), \n    columns=['w', 'x', 'y', 'z']\n)\n\n# Extraction immediate vers la memoire C contigue\ntableau_natif = donnees_massives[['w', 'x', 'y', 'z']].to_numpy()\ndistances_rapides = np.linalg.norm(tableau_natif, axis=1)\n<\/code><\/pre>\n<p>Le passage par la m\u00e9thode <code>.to_numpy()<\/code> extrait le tampon m\u00e9moire contigu sous-jacent, \u00e9liminant la surcouche de gestion d&rsquo;index de Pandas. Sur un \u00e9chantillon de 50 000 lignes, cette transition vectorielle pure r\u00e9duit r\u00e9guli\u00e8rement le temps d&rsquo;ex\u00e9cution de plusieurs secondes \u00e0 quelques millisecondes, soit un facteur d&rsquo;acc\u00e9l\u00e9ration pouvant exc\u00e9der un ratio de 100 pour 1.<\/p>\n<h2>7. Application dans Scikit-Learn et les algorithmes d&rsquo;apprentissage automatique<\/h2>\n<h3>7.1 Matrice de distance avec sklearn.metrics.pairwise.euclidean_distances<\/h3>\n<p>Au sein de la biblioth\u00e8que de r\u00e9f\u00e9rence pour l&rsquo;apprentissage automatique <a rel=\"noopener noreferrer\" href=\"https:\/\/scikit-learn.org\/\">Scikit-Learn<\/a>, le calcul des proximit\u00e9s g\u00e9om\u00e9triques est orchestr\u00e9 par le module <code>sklearn.metrics.pairwise<\/code>. La fonction <code>euclidean_distances<\/code> constitue l&rsquo;outil central pour \u00e9valuer les similarit\u00e9s au sein des pipelines de mod\u00e9lisation :<\/p>\n<pre><code>import numpy as np\nfrom sklearn.metrics.pairwise import euclidean_distances\n\nmatrice_echantillons = np.array([[0, 1], [1, 1], [1, 0], [2, 2]])\nmatrice_resultat = euclidean_distances(matrice_echantillons, matrice_echantillons)\n<\/code><\/pre>\n<p>Cette impl\u00e9mentation offre plusieurs arguments hautement strat\u00e9giques :<\/p>\n<ul>\n<li>Le param\u00e8tre <code>squared=True<\/code> permet de renvoyer directement le carr\u00e9 de la distance euclidienne (<span class=\"arabpsy-math-inline\" data-latex=\"|x - y|^2\">$|x &#8211; y|^2$<\/span>). Dans de nombreux algorithmes, tels que l&rsquo;optimisation des centres de gravit\u00e9 ou la r\u00e9gularisation par moindres carr\u00e9s, la racine carr\u00e9e est superflue pour la prise de d\u00e9cision ordinale et peut \u00eatre omise pour \u00e9pargner des cycles processeur pr\u00e9cieux.<\/li>\n<li>Le support des matrices creuses (<em>scipy.sparse matrices<\/em>) : <code>euclidean_distances<\/code> est capable de calculer la distance euclidienne entre des repr\u00e9sentations vectorielles compress\u00e9es (formats CSR ou CSC) sans mat\u00e9rialiser les z\u00e9ros en m\u00e9moire, \u00e9vitant ainsi l&rsquo;explosion de l&rsquo;occupation vive lors du traitement de sacs de mots (<em>Bag-of-Words<\/em>) ou d&rsquo;encodages disjonctifs.<\/li>\n<\/ul>\n<h3>7.2 R\u00f4le central dans l&rsquo;algorithme des k plus proches voisins (k-NN)<\/h3>\n<p>L&rsquo;algorithme de classification et de r\u00e9gression des <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span> plus proches voisins (<a rel=\"noopener noreferrer\" href=\"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html\">k-Nearest Neighbors<\/a>) illustre l&rsquo;usage op\u00e9rationnel direct de la distance euclidienne. La r\u00e8gle de d\u00e9cision affecte \u00e0 une requ\u00eate inconnue la classe majoritaire parmi les <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span> instances les plus proches dans l&rsquo;espace des caract\u00e9ristiques :<\/p>\n<pre><code>from sklearn.neighbors import KNeighborsClassifier\nimport numpy as np\n\nX_entrainement = np.array([[1.0, 2.0], [1.5, 1.8], [5.0, 8.0], [6.0, 9.0]])\ny_entrainement = np.array([0, 0, 1, 1])\n\nclassificateur_knn = KNeighborsClassifier(n_neighbors=3, metric='euclidean', algorithm='auto')\nclassificateur_knn.fit(X_entrainement, y_entrainement)\n\npoint_test = np.array([[2.0, 2.0]])\nclasse_predite = classificateur_knn.predict(point_test)\n<\/code><\/pre>\n<p>Pour s&rsquo;affranchir d&rsquo;une recherche exhaustive de complexit\u00e9 <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N \\times d)\">$\\mathcal{O}(N \\times d)$<\/span> lors de la phase d&rsquo;inf\u00e9rence (qui requiert de calculer la distance \u00e0 l&rsquo;int\u00e9gralit\u00e9 des points du corpus), Scikit-Learn bascule automatiquement vers des structures de donn\u00e9es en arborescence spatiale lorsque les dimensions sont mod\u00e9r\u00e9es :<\/p>\n<ul>\n<li><strong>KD-Tree :<\/strong> Partitionne r\u00e9cursivement l&rsquo;espace cart\u00e9sien le long des axes m\u00e9dians, \u00e9laguant de larges portions de l&rsquo;espace gr\u00e2ce \u00e0 l&rsquo;in\u00e9galit\u00e9 triangulaire et r\u00e9duisant la complexit\u00e9 de recherche en moyenne \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(\\log N)\">$\\mathcal{O}(\\log N)$<\/span>.<\/li>\n<li><strong>Ball-Tree :<\/strong> Structure l&rsquo;espace sous la forme d&rsquo;hypersph\u00e8res imbriqu\u00e9es, d\u00e9montrant une r\u00e9silience sup\u00e9rieure lorsque la dimension <span class=\"arabpsy-math-inline\" data-latex=\"d\">$d$<\/span> de l&rsquo;espace commence \u00e0 cro\u00eetre.<\/li>\n<\/ul>\n<h3>7.3 Convergence et minimisation de l&rsquo;inertie dans le partitionnement K-Means<\/h3>\n<p>L&rsquo;algorithme de regroupement non supervis\u00e9 des <a rel=\"noopener noreferrer\" href=\"https:\/\/scikit-learn.org\/stable\/modules\/clustering.html#k-means\">K-Means<\/a> s&rsquo;appuie explicitement sur la m\u00e9trique euclidienne pour partitionner un nuage d&rsquo;observations en <span class=\"arabpsy-math-inline\" data-latex=\"K\">$K$<\/span> sous-ensembles homog\u00e8nes. L&rsquo;objectif math\u00e9matique consiste \u00e0 minimiser la variance intra-classe (ou inertie thermique totale) formul\u00e9e comme suit :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"J = \\sum_{k=1}^{K} \\sum_{x_i in S_k} |x_i - \\mu_k|_2^2\">$$J = \\sum_{k=1}^{K} \\sum_{x_i in S_k} |x_i &#8211; \\mu_k|_2^2$$<\/span><\/p>\n<p>o\u00f9 <span class=\"arabpsy-math-inline\" data-latex=\"\\mu_k\">$\\mu_k$<\/span> repr\u00e9sente le barycentre (centro\u00efde g\u00e9om\u00e9trique) associ\u00e9 au cluster <span class=\"arabpsy-math-inline\" data-latex=\"S_k\">$S_k$<\/span>. La validit\u00e9 math\u00e9matique de la convergence de l&rsquo;algorithme de Lloyd d\u00e9pend int\u00e9gralement de la norme euclidienne : le barycentre qui minimise la somme des distances quadratiques correspond pr\u00e9cis\u00e9ment \u00e0 la moyenne arithm\u00e9tique des coordonn\u00e9es du groupe.<\/p>\n<p>Si l&rsquo;on substituait arbitrairement la distance de Manhattan (<span class=\"arabpsy-math-inline\" data-latex=\"L_1\">$L_1$<\/span>) \u00e0 la distance euclidienne sans modifier la mise \u00e0 jour des centres par la moyenne, l&rsquo;algorithme ne convergerait plus n\u00e9cessairement vers un minimum stable de la fonction de co\u00fbt, car la m\u00e9diane g\u00e9om\u00e9trique devrait alors remplacer la moyenne arithm\u00e9tique (comme c&rsquo;est le cas dans l&rsquo;algorithme <span class=\"arabpsy-math-inline\" data-latex=\"K\">$K$<\/span>-Medians). Il existe donc une interd\u00e9pendance th\u00e9orique stricte entre la g\u00e9om\u00e9trie euclidienne et les m\u00e9thodes d&rsquo;agr\u00e9gation centro\u00efdale.<\/p>\n<h2>8. Pr\u00e9traitement obligatoire des donn\u00e9es et sensibilit\u00e9 aux \u00e9chelles<\/h2>\n<h3>8.1 L&rsquo;effet disproportionn\u00e9 des \u00e9carts d&rsquo;\u00e9chelle sur la distance euclidienne<\/h3>\n<p>La distance euclidienne traite l&rsquo;espace vectoriel comme isotrope : une variation num\u00e9rique d&rsquo;une unit\u00e9 le long de la dimension <span class=\"arabpsy-math-inline\" data-latex=\"x_1\">$x_1$<\/span> produit exactement le m\u00eame impact g\u00e9om\u00e9trique qu&rsquo;une variation d&rsquo;une unit\u00e9 le long de la dimension <span class=\"arabpsy-math-inline\" data-latex=\"x_2\">$x_2$<\/span>. Cette neutralit\u00e9 math\u00e9matique devient un \u00e9cueil redoutable lorsque les variables descriptives d&rsquo;un syst\u00e8me poss\u00e8dent des unit\u00e9s physiques h\u00e9t\u00e9rog\u00e8nes ou des dispersions statistiques divergentes.<\/p>\n<p>Consid\u00e9rons un sc\u00e9nario empirique comparant deux attributs descriptifs : le revenu annuel d&rsquo;un individu exprim\u00e9 en euros (dont les variations s&rsquo;\u00e9talent sur des dizaines de milliers d&rsquo;unit\u00e9s) et l&rsquo;\u00e2ge exprim\u00e9 en ann\u00e9es (dont la plage de variation exc\u00e8de rarement quelques dizaines d&rsquo;unit\u00e9s). Le calcul des distances quadratiques sera math\u00e9matiquement submerg\u00e9 par les diff\u00e9rences de revenus, r\u00e9duisant la dimension relative \u00e0 l&rsquo;\u00e2ge \u00e0 un niveau de bruit statistiquement n\u00e9gligeable. Sans ajustement d&rsquo;\u00e9chelle, l&rsquo;espace m\u00e9trique subit une distorsion artificielle qui fausse int\u00e9gralement les regroupements topologiques et les classifications spatiales.<\/p>\n<h3>8.2 Standardisation Z-Score via StandardScaler<\/h3>\n<p>Pour neutraliser ces distorsions m\u00e9triques et r\u00e9tablir la comparabilit\u00e9 des dimensions au sein de l&rsquo;espace euclidien, la transformation Z-score constitue la m\u00e9thode d&rsquo;\u00e9talonnage param\u00e9trique standard. Cette proc\u00e9dure recentre chaque variable sur sa moyenne empirique <span class=\"arabpsy-math-inline\" data-latex=\"\\mu\">$\\mu$<\/span> et la divise par son \u00e9cart-type statistique <span class=\"arabpsy-math-inline\" data-latex=\"\\sigma\">$\\sigma$<\/span> :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"z = \\frac{x - \\mu}{\\sigma}\">$$z = \\frac{x &#8211; \\mu}{\\sigma}$$<\/span><\/p>\n<p>Sous Scikit-Learn, cette transformation est ex\u00e9cut\u00e9e par la classe <code>StandardScaler<\/code> :<\/p>\n<pre><code>from sklearn.preprocessing import StandardScaler\nimport numpy as np\n\ndonnees_brutes = np.array([\n    [25000.0, 22.0],\n    [85000.0, 54.0],\n    [32000.0, 29.0],\n    [110000.0, 61.0]\n])\n\ncalibreur = StandardScaler()\ndonnees_standardisees = calibreur.fit_transform(donnees_brutes)\n\n# Calcul des distances sur variables homogenes\ndistance_post_standardisation = np.linalg.norm(\n    donnees_standardisees[0] - donnees_standardisees[1]\n)\n<\/code><\/pre>\n<p>\u00c0 l&rsquo;issue de cette op\u00e9ration, chaque composante vectorielle pr\u00e9sente une esp\u00e9rance nulle et une variance unitaire (<span class=\"arabpsy-math-inline\" data-latex=\"\\sigma^2 = 1\">$\\sigma^2 = 1$<\/span>). Dans cet espace norm\u00e9, les axes contribuent de mani\u00e8re \u00e9quitable \u00e0 la variance globale, permettant \u00e0 la distance euclidienne d&rsquo;op\u00e9rer une comparaison g\u00e9om\u00e9trique non biais\u00e9e.<\/p>\n<h3>8.3 Normalisation Min-Max et imputation des valeurs manquantes<\/h3>\n<p>Une alternative fr\u00e9quente \u00e0 la standardisation Z-score r\u00e9side dans la mise \u00e0 l&rsquo;\u00e9chelle Min-Max, ex\u00e9cut\u00e9e via <code>MinMaxScaler<\/code>. Cette normalisation r\u00e9\u00e9chelonne lin\u00e9airement chaque composante au sein d&rsquo;un intervalle num\u00e9rique born\u00e9, classiquement l&rsquo;intervalle unit\u00e9 <span class=\"arabpsy-math-inline\" data-latex=\"[0, 1]\">$[0, 1]$<\/span> :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"x_{\\text{norm}} = \\frac{x - x_{\\min}}{x_{\\max} - x_{\\min}}\">$$x_{\\text{norm}} = \\frac{x &#8211; x_{\\min}}{x_{\\max} &#8211; x_{\\min}}$$<\/span><\/p>\n<p>Cette approche est particuli\u00e8rement adapt\u00e9e lorsque la borne sup\u00e9rieure et la borne inf\u00e9rieure des ph\u00e9nom\u00e8nes observ\u00e9s sont connues \u00e0 l&rsquo;avance et qu&rsquo;aucune distribution gaussienne n&rsquo;est pr\u00e9sum\u00e9e. Cependant, la pr\u00e9sence de valeurs aberrantes (<em>outliers<\/em>) peut compresser l&rsquo;immense majorit\u00e9 des observations r\u00e9guli\u00e8res dans une fraction \u00e9troite de l&rsquo;intervalle <span class=\"arabpsy-math-inline\" data-latex=\"[0, 1]\">$[0, 1]$<\/span>, d\u00e9gradant la r\u00e9solution m\u00e9trique locale.<\/p>\n<p>Par ailleurs, la distance euclidienne ne tol\u00e8re math\u00e9matiquement aucune donn\u00e9e manquante (valeur not\u00e9e <code>NaN<\/code> en repr\u00e9sentation flottante). La propagation de toute valeur manquante dans l&rsquo;accumulateur arithm\u00e9tique engendre inexorablement un r\u00e9sultat non d\u00e9fini <code>NaN<\/code> :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"(x_i - \\text{NaN})^2 = \\text{NaN} implies \\sqrt{\\sum dots} = \\text{NaN}\">$$(x_i &#8211; \\text{NaN})^2 = \\text{NaN} implies \\sqrt{\\sum dots} = \\text{NaN}$$<\/span><\/p>\n<p>Il est donc obligatoire d&rsquo;effectuer pr\u00e9alablement une imputation statistique via des modules tels que <code>SimpleImputer<\/code> (par remplacement par la moyenne ou la m\u00e9diane) ou <code>KNNImputer<\/code> avant de soumettre les vecteurs aux op\u00e9rateurs m\u00e9triques.<\/p>\n<h2>9. Applications pratiques en mod\u00e9lisation psychom\u00e9trique et comportementale<\/h2>\n<h3>9.1 Quantification de la ressemblance entre profils de personnalit\u00e9 (Big Five)<\/h3>\n<p>En psychologie diff\u00e9rentielle et computationnelle, le mod\u00e8le des <a rel=\"noopener noreferrer\" href=\"https:\/\/nobaproject.com\/modules\/personality-traits\">Big Five (mod\u00e8le OCEAN)<\/a> quantifie la structure de la personnalit\u00e9 humaine \u00e0 travers cinq dimensions continues orthogonales : Ouverture, Conscienciosit\u00e9, Extraversion, Agr\u00e9abilit\u00e9 et N\u00e9vrosisme. Chaque sujet \u00e9valu\u00e9 peut ainsi \u00eatre repr\u00e9sent\u00e9 par un vecteur descriptif <span class=\"arabpsy-math-inline\" data-latex=\"v in [1, 5]^5\">$v in [1, 5]^5$<\/span> issu de l&rsquo;agr\u00e9gation de r\u00e9ponses \u00e0 des \u00e9chelles de type Likert.<\/p>\n<p>La distance euclidienne permet de mesurer le degr\u00e9 de divergence ou de congruence dispositionnelle entre deux individus. Un \u00e9cart euclidien nul refl\u00e8te une identit\u00e9 de profil sur les cinq dimensions psychologiques :<\/p>\n<pre><code>import numpy as np\n\n# Profils OCEAN normalises sur une echelle ordinale continue de 1 a 5\n# Ordre des indices : [Ouverture, Conscienciosite, Extraversion, Agreabilite, Nevrosisme]\nsujet_reference = np.array([4.2, 3.8, 2.1, 4.5, 1.9])\nsujet_candidat_a = np.array([4.0, 3.9, 2.3, 4.2, 2.1])\nsujet_candidat_b = np.array([1.5, 2.0, 4.8, 2.1, 4.7])\n\ndistance_a = np.linalg.norm(sujet_reference - sujet_candidat_a)\ndistance_b = np.linalg.norm(sujet_reference - sujet_candidat_b)\n\nprint(f\"Indice de dissimilarite profil A : {distance_a:.3f}\")\nprint(f\"Indice de dissimilarite profil B : {distance_b:.3f}\")\n<\/code><\/pre>\n<p>Cette mesure de proximit\u00e9 comportementale fournit un indicateur synth\u00e9tique utilis\u00e9 dans les \u00e9tudes sur la stabilit\u00e9 dyadique, la composition optimale des \u00e9quipes de travail ou la personnalisation de dispositifs d&rsquo;apprentissage.<\/p>\n<h3>9.2 Analyse de donn\u00e9es chronom\u00e9triques et t\u00e2ches de d\u00e9cision lexicale<\/h3>\n<p>Dans les paradigmes de chronom\u00e9trie mentale en sciences cognitives, notamment lors d&rsquo;exp\u00e9riences de d\u00e9cision lexicale, les chercheurs compilent simultan\u00e9ment les temps de r\u00e9action (en millisecondes) et les taux d&rsquo;erreur commis par les sujets expos\u00e9s \u00e0 diverses cat\u00e9gories de stimuli verbaux ou non-verbaux. Un participant peut \u00eatre mod\u00e9lis\u00e9 sous la forme d&rsquo;un vecteur bivari\u00e9 ou multivari\u00e9 refl\u00e9tant son compromis vitesse-pr\u00e9cision (<em>speed-accuracy trade-off<\/em>).<\/p>\n<p>L&rsquo;\u00e9valuation de la distance euclidienne par rapport \u00e0 un profil comportemental canonique (d\u00e9fini par le barycentre du groupe contr\u00f4le) permet de rep\u00e9rer objectivement les profils atypiques ou de d\u00e9tecter des strat\u00e9gies de traitement singuli\u00e8res :<\/p>\n<pre><code>import numpy as np\nfrom sklearn.preprocessing import StandardScaler\n\n# Colonnes : [Temps de Reaction Moyen (ms), Pourcentage d'Erreurs (%)]\nmesures_cognitives = np.array([\n    [540.0, 4.2],\n    [525.0, 5.1],\n    [580.0, 3.8],\n    [890.0, 22.5],  # Sujet atypique\n    [530.0, 4.8]\n])\n\nmise_a_l_echelle = StandardScaler()\ndonnees_chrono_std = mise_a_l_echelle.fit_transform(mesures_cognitives)\n\n# Determination du barycentre comportemental de la cohorte\nprofil_moyen = np.mean(donnees_chrono_std, axis=0)\n\n# Calcul des distances euclidiennes au profil moyen\nanomalies_distances = np.linalg.norm(donnees_chrono_std - profil_moyen, axis=1)\n<\/code><\/pre>\n<p>L&rsquo;utilisation pr\u00e9alable du <code>StandardScaler<\/code> neutralise la diff\u00e9rence d&rsquo;ordre de grandeur entre les millisecondes (centaines d&rsquo;unit\u00e9s) et les pourcentages d&rsquo;erreurs (dizaines d&rsquo;unit\u00e9s), conf\u00e9rant \u00e0 l&rsquo;\u00e9cart g\u00e9om\u00e9trique r\u00e9sultant une validit\u00e9 diagnostique rigoureuse.<\/p>\n<h3>9.3 \u00c9chelonnement multidimensionnel (MDS) et repr\u00e9sentations spatiales de stimuli<\/h3>\n<p>L&rsquo;\u00e9chelonnement multidimensionnel (<a rel=\"noopener noreferrer\" href=\"https:\/\/scikit-learn.org\/stable\/modules\/manifold.html#multidimensional-scaling\">Multidimensional Scaling ou MDS<\/a>) est une m\u00e9thode d&rsquo;analyse psychom\u00e9trique majeure visant \u00e0 reconstituer une configuration spatiale g\u00e9om\u00e9trique \u00e0 partir d&rsquo;une matrice empirique de proximit\u00e9s ou de jugements de dissimilarit\u00e9 entre stimuli perceptifs (sons, couleurs, visages).<\/p>\n<p>Le mod\u00e8le optimise les coordonn\u00e9es spatiales des stimuli au sein d&rsquo;un espace euclidien restreint de dimension r\u00e9duite (g\u00e9n\u00e9ralement <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbb{R}^2\">$\\mathbb{R}^2$<\/span> ou <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbb{R}^3\">$\\mathbb{R}^3$<\/span>) de mani\u00e8re \u00e0 ce que les distances euclidiennes entre les points projet\u00e9s correspondent le plus fid\u00e8lement possible aux dissimilarit\u00e9s psychologiques per\u00e7ues :<\/p>\n<pre><code>import numpy as np\nfrom sklearn.manifold import MDS\n\n# Matrice de jugements de dissimilarite subjectifs entre 4 stimuli auditifs\nmatrice_dissimilarites = np.array([\n    [0.0, 2.5, 5.3, 8.1],\n    [2.5, 0.0, 3.2, 6.7],\n    [5.3, 3.2, 0.0, 4.0],\n    [8.1, 6.7, 4.0, 0.0]\n])\n\nprojection_mds = MDS(\n    n_components=2, \n    dissimilarity='precomputed', \n    random_state=42,\n    normalized_stress='auto'\n)\ncoordonnees_spatiales = projection_mds.fit_transform(matrice_dissimilarites)\n\n# Le stress mesure l'ecart d'ajustement entre la geometrie euclidienne et les jugements percus\nprint(f\"Stress d'ajustement : {projection_mds.stress_:.4f}\")\n<\/code><\/pre>\n<p>La minimisation de la fonction de perte (nomm\u00e9e <em>Stress<\/em>) permet d&rsquo;\u00e9tudier directement les axes psychologiques sous-tendant la cat\u00e9gorisation perceptive, d\u00e9montrant comment l&rsquo;espace euclidien sert de m\u00e9taphore computationnelle pour mod\u00e9liser la structure des repr\u00e9sentations cognitives internes.<\/p>\n<h2>10. Limites conceptuelles et th\u00e9oriques de la m\u00e9trique euclidienne<\/h2>\n<h3>10.1 Le fl\u00e9au de la dimensionnalit\u00e9 (Curse of Dimensionality)<\/h3>\n<p>Lorsque la dimensionnalit\u00e9 de l&rsquo;espace vectoriel d&rsquo;observation <span class=\"arabpsy-math-inline\" data-latex=\"d\">$d$<\/span> augmente de mani\u00e8re substantielle, la g\u00e9om\u00e9trie euclidienne subit une transformation contre-intuitive connue sous le nom de ph\u00e9nom\u00e8ne de <strong>concentration de la mesure<\/strong>. Dans des espaces \u00e0 haute dimension (par exemple <span class=\"arabpsy-math-inline\" data-latex=\"d &gt; 100\">$d > 100$<\/span>), le volume d&rsquo;un hypercube cro\u00eet exponentiellement par rapport \u00e0 celui d&rsquo;une hypersph\u00e8re inscrite, rel\u00e9guant la quasi-totalit\u00e9 de la masse volumique vers la p\u00e9riph\u00e9rie de l&rsquo;espace d&rsquo;\u00e9chantillonnage.<\/p>\n<p>Sur le plan m\u00e9trique, ce ph\u00e9nom\u00e8ne entra\u00eene une convergence progressive des distances relatives : la variance de la distribution des distances euclidiennes entre paires de points s&rsquo;amenuise comparativement \u00e0 leur esp\u00e9rance math\u00e9matique. Formellement, pour des distributions de donn\u00e9es classiques :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\lim_{d to \\infty} \\frac{d_{\\max} - d_{\\min}}{d_{\\min}} to 0\">$$\\lim_{d to \\infty} \\frac{d_{\\max} &#8211; d_{\\min}}{d_{\\min}} to 0$$<\/span><\/p>\n<p>Cette convergence rend tous les points virtuellement \u00e9quidistants les uns des autres. En cons\u00e9quence, les algorithmes de fouille spatiale (comme les <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span>-NN ou les arbres de recherche spatiale) perdent leur pouvoir discriminant, car la notion m\u00eame de \u00ab\u00a0voisinage imm\u00e9diat\u00a0\u00bb s&rsquo;estompe dans l&rsquo;immensit\u00e9 combinatoire de l&rsquo;espace.<\/p>\n<h3>10.2 Vuln\u00e9rabilit\u00e9 face aux donn\u00e9es aberrantes (Outliers)<\/h3>\n<p>L&rsquo;op\u00e9ration centrale de la distance euclidienne repose sur la quadrature arithm\u00e9tique des \u00e9carts univari\u00e9s : <span class=\"arabpsy-math-inline\" data-latex=\"(p_i - q_i)^2\">$(p_i &#8211; q_i)^2$<\/span>. Cette caract\u00e9ristique alg\u00e9brique amplifie de fa\u00e7on quadratique l&rsquo;influence relative des \u00e9carts majeurs par rapport aux \u00e9carts mineurs. Si une observation pr\u00e9sente une d\u00e9viation substantielle sur une seule coordonn\u00e9e \u2014 qu&rsquo;elle d\u00e9coule d&rsquo;un dysfonctionnement de capteur ou d&rsquo;une erreur de saisie \u2014, cette d\u00e9viation dominera math\u00e9matiquement la somme quadratique globale.<\/p>\n<p>Cette vuln\u00e9rabilit\u00e9 contraste vivement avec les propri\u00e9t\u00e9s des m\u00e9triques dites robustes, \u00e0 l&rsquo;instar de la distance de Manhattan (<span class=\"arabpsy-math-inline\" data-latex=\"L_1\">$L_1$<\/span>), qui pond\u00e8re lin\u00e9airement les d\u00e9viations sans leur appliquer d&rsquo;amplification exponentielle. Dans les calculs d&rsquo;apprentissage automatique, tels que le partitionnement K-Means, une poign\u00e9e d&rsquo;individus aberrants suffit \u00e0 d\u00e9vier drastiquement la trajectoire des centro\u00efdes, d\u00e9gradant la repr\u00e9sentativit\u00e9 des partitions obtenues. Il est donc imp\u00e9ratif d&rsquo;envisager soit un filtrage robuste des donn\u00e9es extr\u00eames, soit l&rsquo;usage de fonctions de perte r\u00e9gularis\u00e9es (comme la perte de Huber ou la distance de Tukey) lorsque la pr\u00e9sence d&rsquo;outliers est suspect\u00e9e.<\/p>\n<h3>10.3 Hypoth\u00e8se d&rsquo;orthogonalit\u00e9 versus corr\u00e9lations inter-variables<\/h3>\n<p>La distance euclidienne canonique postule implicitement que le syst\u00e8me d&rsquo;axes sous-jacent est orthonorm\u00e9 : les dimensions sont suppos\u00e9es orthogonales et mutuellement d\u00e9corr\u00e9l\u00e9es sur le plan statistique. Or, dans les donn\u00e9es empiriques r\u00e9elles (donn\u00e9es physiologiques, \u00e9conomiques ou comportementales), les variables d&rsquo;observation pr\u00e9sentent fr\u00e9quemment des colin\u00e9arit\u00e9s intenses ou des d\u00e9pendances lin\u00e9aires marqu\u00e9es.<\/p>\n<p>Consid\u00e9rons deux variables <span class=\"arabpsy-math-inline\" data-latex=\"x_1\">$x_1$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"x_2\">$x_2$<\/span> fortement corr\u00e9l\u00e9es (par exemple, la taille et la longueur des membres inf\u00e9rieurs d&rsquo;un individu). La m\u00e9trique euclidienne comptera deux fois la m\u00eame information morphologique sous-jacente, surpond\u00e9rant artificiellement cette dimension latente au d\u00e9triment des variables ind\u00e9pendantes. Pour lever cette hypoth\u00e8se contraignante, on privil\u00e9gie la <a rel=\"noopener noreferrer\" href=\"https:\/\/mathworld.wolfram.com\/MahalanobisDistance.html\">distance de Mahalanobis<\/a>, qui int\u00e8gre formellement la matrice de covariance empirique <span class=\"arabpsy-math-inline\" data-latex=\"\\Sigma\">$\\Sigma$<\/span> du nuage d&rsquo;observations :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"d_M(p, q) = \\sqrt{(p - q)^T \\Sigma^{-1} (p - q)}\">$$d_M(p, q) = \\sqrt{(p &#8211; q)^T \\Sigma^{-1} (p &#8211; q)}$$<\/span><\/p>\n<p>La matrice de covariance inverse <span class=\"arabpsy-math-inline\" data-latex=\"\\Sigma^{-1}\">$\\Sigma^{-1}$<\/span> op\u00e8re une rotation et une mise \u00e0 l&rsquo;\u00e9chelle qui d\u00e9corr\u00e8lent les axes et normalisent les variances, fournissant une mesure d&rsquo;\u00e9cart statistique invariante face aux transformations affines et exempte des biais d&rsquo;interd\u00e9pendance.<\/p>\n<h2>11. Benchmarks comparatifs de performance d&rsquo;ex\u00e9cution en Python<\/h2>\n<h3>11.1 Protocole d&rsquo;\u00e9talonnage exp\u00e9rimental avec le module timeit<\/h3>\n<p>L&rsquo;\u00e9valuation des performances des diff\u00e9rentes approches de calcul de la distance euclidienne exige un protocole exp\u00e9rimental m\u00e9thodique pour garantir la reproductibilit\u00e9 des mesures. Le module standard <a rel=\"noopener noreferrer\" href=\"https:\/\/docs.python.org\/3\/library\/timeit.html\">timeit<\/a> constitue l&rsquo;instrument de r\u00e9f\u00e9rence pour mesurer des temps d&rsquo;ex\u00e9cution en Python. Il d\u00e9sactive temporairement le ramasse-miettes (<em>garbage collector<\/em>) et r\u00e9it\u00e8re les \u00e9valuations afin de minimiser les perturbations introduites par l&rsquo;ordonnanceur du syst\u00e8me d&rsquo;exploitation.<\/p>\n<p>Le protocole d&rsquo;\u00e9valuation suivant permet de comparer les diff\u00e9rentes impl\u00e9mentations pr\u00e9sent\u00e9es sur des vecteurs de dimensionnalit\u00e9s croissantes (de <span class=\"arabpsy-math-inline\" data-latex=\"d = 10\">$d = 10$<\/span> \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"d = 1,000,000\">$d = 1,000,000$<\/span>) :<\/p>\n<pre><code>import timeit\nimport numpy as np\n\ndef benchmark_distance(dimension, repetitions=1000):\n    setup_code = f\"\"\"\nimport math\nimport numpy as np\nfrom scipy.spatial.distance import euclidean\n\nvec_a_list = np.random.randn({dimension}).tolist()\nvec_b_list = np.random.randn({dimension}).tolist()\n\nvec_a_np = np.array(vec_a_list)\nvec_b_np = np.array(vec_b_list)\n\"\"\"\n    \n    test_python_pur = \"math.sqrt(sum((a - b)**2 for a, b in zip(vec_a_list, vec_b_list)))\"\n    test_math_dist = \"math.dist(vec_a_list, vec_b_list)\"\n    test_numpy_norm = \"np.linalg.norm(vec_a_np - vec_b_np)\"\n    test_numpy_dot = \"np.sqrt(np.dot(vec_a_np - vec_b_np, vec_a_np - vec_b_np))\"\n    test_scipy = \"euclidean(vec_a_np, vec_b_np)\"\n    \n    t_py = timeit.timeit(test_python_pur, setup=setup_code, number=repetitions)\n    t_dist = timeit.timeit(test_math_dist, setup=setup_code, number=repetitions)\n    t_norm = timeit.timeit(test_numpy_norm, setup=setup_code, number=repetitions)\n    t_dot = timeit.timeit(test_numpy_dot, setup=setup_code, number=repetitions)\n    t_scipy = timeit.timeit(test_scipy, setup=setup_code, number=repetitions)\n    \n    return {'Dimension': dimension, 'Pure Python': t_py, 'math.dist': t_dist, \n            'np.linalg.norm': t_norm, 'np.dot': t_dot, 'SciPy': t_scipy}\n<\/code><\/pre>\n<h3>11.2 Comparaison empirique : Python pur, math.dist, NumPy et SciPy<\/h3>\n<p>L&rsquo;ex\u00e9cution syst\u00e9matique de ce protocole sur diff\u00e9rentes \u00e9chelles dimensionnelles met en lumi\u00e8re des divergences de performance notables, r\u00e9sum\u00e9es dans le profil empirique suivant :<\/p>\n<ul>\n<li><strong>Vecteurs courts (Dimension 3 \u00e0 10) :<\/strong> La fonction native <code>math.dist()<\/code> domine syst\u00e9matiquement ses concurrents. Les biblioth\u00e8ques scientifiques comme NumPy et SciPy subissent une p\u00e9nalit\u00e9 li\u00e9e au surco\u00fbt d&rsquo;appel (<em>overhead<\/em>) de leurs fonctions compil\u00e9es et \u00e0 l&rsquo;encapsulation dans des structures C, ce qui les rend 2 \u00e0 5 fois plus lentes que <code>math.dist()<\/code> sur de faibles dimensions. L&rsquo;approche en Python pur avec <code>zip()<\/code> reste toutefois la plus lente en raison du co\u00fbt d&rsquo;instanciation des it\u00e9rateurs.<\/li>\n<li><strong>Vecteurs moyens (Dimension 100 \u00e0 1 000) :<\/strong> Un point de bascule s&rsquo;op\u00e8re. L&rsquo;approche vectoris\u00e9e <code>np.sqrt(np.dot(...))<\/code> surpasse l&rsquo;ensemble des alternatives. Les instructions vectorielles SIMD permettent de traiter simultan\u00e9ment plusieurs \u00e9l\u00e9ments en virgule flottante au sein du pipeline arithm\u00e9tique, compensant largement le surco\u00fbt d&rsquo;initialisation de l&rsquo;environnement NumPy.<\/li>\n<li><strong>Vecteurs denses massifs (Dimension 10 000 \u00e0 1 000 000) :<\/strong> L&rsquo;approche en Python pur s&rsquo;effondre en raison de la saturation du cache m\u00e9moire et du co\u00fbt d&rsquo;interpr\u00e9tation du bytecode. Les m\u00e9thodes NumPy vectoris\u00e9es (<code>np.dot<\/code> et <code>np.linalg.norm<\/code>) s&rsquo;av\u00e8rent de 50 \u00e0 150 fois plus v\u00e9loces que les boucles pures, exploitant pleinement la bande passante de la m\u00e9moire vive et la parall\u00e9lisation interne des biblioth\u00e8ques BLAS.<\/li>\n<\/ul>\n<h3>11.3 Acc\u00e9l\u00e9ration mat\u00e9rielle et compilation Just-In-Time avec Numba<\/h3>\n<p>Pour combiner la lisibilit\u00e9 d&rsquo;une boucle imp\u00e9rative classique et les performances optimales du code machine compil\u00e9, la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/numba.pydata.org\/\">Numba<\/a> offre un compilateur Just-In-Time (JIT) qui convertit des fonctions Python d\u00e9cor\u00e9es directement en instructions assembleur via l&rsquo;infrastructure <a rel=\"noopener noreferrer\" href=\"https:\/\/llvm.org\/\">LLVM<\/a> :<\/p>\n<pre><code>import numba\nimport numpy as np\n\n@numba.njit(fastmath=True, parallel=True)\ndef distance_euclidienne_numba(vecteur_u, vecteur_v):\n    taille = vecteur_u.shape[0]\n    sommation = 0.0\n    for i in numba.prange(taille):\n        difference = vecteur_u[i] - vecteur_v[i]\n        sommation += difference * difference\n    return np.sqrt(sommation)\n<\/code><\/pre>\n<p>Cette impl\u00e9mentation mobilise des optimisations mat\u00e9rielles avanc\u00e9es :<\/p>\n<ul>\n<li>Le mode <code>@numba.njit<\/code> (sans Python) contourne totalement l&rsquo;interpr\u00e9teur CPython et le verrou global de l&rsquo;interpr\u00e9teur (GIL &#8211; <em>Global Interpreter Lock<\/em>).<\/li>\n<li>L&rsquo;argument <code>fastmath=True<\/code> autorise le r\u00e9ordonnancement des calculs en virgule flottante non conformes \u00e0 la norme IEEE 754 stricte, favorisant la vectorisation agressive par le compilateur.<\/li>\n<li>L&rsquo;instruction <code>numba.prange<\/code> combin\u00e9e \u00e0 <code>parallel=True<\/code> distribue automatiquement les segments de la sommation quadratique sur l&rsquo;ensemble des c\u0153urs physiques du microprocesseur gr\u00e2ce \u00e0 des threads de bas niveau (OpenMP\/TBB), surpassant fr\u00e9quemment les routines BLAS standard sur les tr\u00e8s grands vecteurs.<\/li>\n<\/ul>\n<h2>12. Guide d\u00e9cisionnel, bonnes pratiques de programmation et synth\u00e8se<\/h2>\n<h3>12.1 Validation d\u00e9fensive des types et programmation robuste<\/h3>\n<p>Le d\u00e9veloppement de biblioth\u00e8ques scientifiques exige une programmation d\u00e9fensive rigoureuse pour garantir l&rsquo;int\u00e9grit\u00e9 des calculs. L&rsquo;int\u00e9gration des annotations de type statiques (<em>Type Hints<\/em>) r\u00e9gies par la <a rel=\"noopener noreferrer\" href=\"https:\/\/peps.python.org\/pep-0484\/\">PEP 484<\/a>, coupl\u00e9e \u00e0 des v\u00e9rifications de pr\u00e9conditions num\u00e9riques, pr\u00e9vient les comportements ind\u00e9termin\u00e9s :<\/p>\n<pre><code>from typing import Union, Sequence\nimport numpy as np\n\ndef distance_euclidienne_defensive(\n    vecteur_a: Union[Sequence[float], np.ndarray], \n    vecteur_b: Union[Sequence[float], np.ndarray]\n) -> float:\n    # Coercition controlee vers des structures matricielles NumPy\n    arr_a = np.asarray(vecteur_a, dtype=np.float64)\n    arr_b = np.asarray(vecteur_b, dtype=np.float64)\n    \n    if arr_a.shape != arr_b.shape:\n        raise ValueError(\n            f\"Incompatibilite dimensionnelle : vecteur_a={arr_a.shape}, vecteur_b={arr_b.shape}\"\n        )\n        \n    if not (np.all(np.isfinite(arr_a)) and np.all(np.isfinite(arr_b))):\n        raise FloatingPointError(\"Presence interdite de valeurs non finies (NaN ou Inf).\")\n        \n    ecart = arr_a - arr_b\n    return float(np.sqrt(np.dot(ecart, ecart)))\n<\/code><\/pre>\n<p>Ce patron d&rsquo;impl\u00e9mentation garantit une conformit\u00e9 de type stricte, valide l&rsquo;absence de valeurs ind\u00e9finies (<code>NaN<\/code>) ou infinies (<code>Inf<\/code>), et s&rsquo;int\u00e8gre harmonieusement avec des outils d&rsquo;analyse statique de code tels que <code>mypy<\/code> et des suites de tests unitaires comme <code>pytest<\/code>.<\/p>\n<h3>12.2 Arbre d\u00e9cisionnel pour le choix de la biblioth\u00e8que ad\u00e9quate<\/h3>\n<p>Le choix de l&rsquo;outil appropri\u00e9 pour calculer une distance euclidienne d\u00e9coule de la nature des structures de donn\u00e9es manipul\u00e9es, de la volum\u00e9trie des observations et des contraintes d&rsquo;infrastructure logicielle. Le protocole d\u00e9cisionnel suivant permet d&rsquo;orienter ce choix :<\/p>\n<ul>\n<li><strong>Environnements contraints et d\u00e9pendances z\u00e9ro :<\/strong> Pour des microservices l\u00e9gers, des syst\u00e8mes embarqu\u00e9s ou des fonctions serverless interdisant le d\u00e9ploiement de d\u00e9pendances C lourdes :\n<ul>\n<li>Utiliser <code>math.dist()<\/code> pour des points isol\u00e9s en Python 3.8+.<\/li>\n<li>Employer une boucle imp\u00e9rative pure avec <code>math.sqrt()<\/code> pour des contextes n\u00e9cessitant une compatibilit\u00e9 descendante absolue.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Calculs vectoriels et manipulations matricielles g\u00e9n\u00e9rales :<\/strong> D\u00e8s lors que le calcul s&rsquo;inscrit au sein d&rsquo;un pipeline d&rsquo;analyse de donn\u00e9es standard :\n<ul>\n<li>Utiliser <code>np.linalg.norm(a - b)<\/code> pour son expressivit\u00e9 et sa robustesse face aux d\u00e9rives num\u00e9riques.<\/li>\n<li>Privil\u00e9gier <code>np.sqrt(np.dot(diff, diff))<\/code> pour optimiser les performances sur des paires de vecteurs uniques denses.<\/li>\n<li>Adopter la formulation par expansion de bin\u00f4me avec <code>np.dot<\/code> pour le pairwise d&rsquo;ensembles mod\u00e9r\u00e9s \u00e9vitant les surco\u00fbts tensoriels.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Comparaisons par paires exhaustives et apprentissage automatique :<\/strong>\n<ul>\n<li>Utiliser <code>scipy.spatial.distance.pdist<\/code> pour calculer la matrice condens\u00e9e sans redondance d&rsquo;un ensemble unique d&rsquo;observations.<\/li>\n<li>Utiliser <code>scipy.spatial.distance.cdist<\/code> pour mesurer les proximit\u00e9s entre deux ensembles d&rsquo;observations disjoints.<\/li>\n<li>Recourir \u00e0 <code>sklearn.metrics.pairwise.euclidean_distances<\/code> au sein des pipelines Scikit-Learn n\u00e9cessitant le support des matrices creuses ou l&rsquo;utilisation du param\u00e8tre <code>squared=True<\/code>.<\/li>\n<li>Employer <code>Numba<\/code> avec l&rsquo;option <code>parallel=True<\/code> sur des boucles personnalis\u00e9es massives ex\u00e9cut\u00e9es sur des architectures multicoeurs d\u00e9di\u00e9es.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>12.3 R\u00e9capitulatif des syntaxes canoniques et m\u00e9mofiche op\u00e9rationnelle<\/h3>\n<p>Le tableau comparatif suivant synth\u00e9tise les m\u00e9thodes de r\u00e9f\u00e9rence pour calculer la distance euclidienne en Python, en pr\u00e9cisant leurs signatures, leurs types de retour et leurs contextes d&rsquo;utilisation privil\u00e9gi\u00e9s :<\/p>\n<table>\n<thead>\n<tr>\n<th>Biblioth\u00e8que \/ Module<\/th>\n<th>Signature d&rsquo;appel type<\/th>\n<th>Type de donn\u00e9es attendu<\/th>\n<th>Complexit\u00e9 m\u00e9moire<\/th>\n<th>Cas d&rsquo;usage pr\u00e9f\u00e9rentiel<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Module math<\/strong><\/td>\n<td><code>math.dist(p, q)<\/code><\/td>\n<td>It\u00e9rables natifs (listes, tuples)<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(1)\">$\\mathcal{O}(1)$<\/span><\/td>\n<td>Points 1D isol\u00e9s, microservices sans d\u00e9pendances externes.<\/td>\n<\/tr>\n<tr>\n<td><strong>NumPy (linalg)<\/strong><\/td>\n<td><code>np.linalg.norm(u - v)<\/code><\/td>\n<td><code>np.ndarray<\/code> num\u00e9rique<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(d)\">$\\mathcal{O}(d)$<\/span><\/td>\n<td>Calcul vectoriel interactif et v\u00e9rification dimensionnelle standard.<\/td>\n<\/tr>\n<tr>\n<td><strong>NumPy (dot)<\/strong><\/td>\n<td><code>np.sqrt(np.dot(d, d))<\/code><\/td>\n<td><code>np.ndarray<\/code> unidimensionnel<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(d)\">$\\mathcal{O}(d)$<\/span><\/td>\n<td>Optimisation de la latence sur des vecteurs denses individuels.<\/td>\n<\/tr>\n<tr>\n<td><strong>SciPy (pdist)<\/strong><\/td>\n<td><code>pdist(X, 'euclidean')<\/code><\/td>\n<td>Matrice 2D <span class=\"arabpsy-math-inline\" data-latex=\"(N \\times d)\">$(N \\times d)$<\/span><\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N^2 \/ 2)\">$\\mathcal{O}(N^2 \/ 2)$<\/span><\/td>\n<td>G\u00e9n\u00e9ration compacte non redondante de matrices de distance intra-\u00e9chantillon.<\/td>\n<\/tr>\n<tr>\n<td><strong>SciPy (cdist)<\/strong><\/td>\n<td><code>cdist(XA, XB, 'euclidean')<\/code><\/td>\n<td>Deux matrices <span class=\"arabpsy-math-inline\" data-latex=\"(N \\times d)\">$(N \\times d)$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"(M \\times d)\">$(M \\times d)$<\/span><\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N \\times M)\">$\\mathcal{O}(N \\times M)$<\/span><\/td>\n<td>Calculs de proximit\u00e9 entre deux collections de points distinctes.<\/td>\n<\/tr>\n<tr>\n<td><strong>Scikit-Learn<\/strong><\/td>\n<td><code>euclidean_distances(X, Y)<\/code><\/td>\n<td>Tableaux denses ou matrices creuses<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(N \\times M)\">$\\mathcal{O}(N \\times M)$<\/span><\/td>\n<td>Pipelines de machine learning, support natif des donn\u00e9es creuses.<\/td>\n<\/tr>\n<tr>\n<td><strong>Numba JIT<\/strong><\/td>\n<td>Fonction d\u00e9cor\u00e9e <code>@njit<\/code><\/td>\n<td>Tableaux contigus C-array<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{O}(1)\">$\\mathcal{O}(1)$<\/span> auxiliaire<\/td>\n<td>Boucles scientifiques personnalis\u00e9es, calculs intensifs sur architectures multicoeurs.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>La ma\u00eetrise du calcul de la distance euclidienne en Python repose sur une compr\u00e9hension claire de ses fondements g\u00e9om\u00e9triques et des caract\u00e9ristiques de l&rsquo;interpr\u00e9teur. En adaptant rigoureusement le choix de l&rsquo;outil algorithmique aux contraintes dimensionnelles et volum\u00e9triques des donn\u00e9es, l&rsquo;ing\u00e9nieur et le chercheur s&rsquo;assurent de concevoir des syst\u00e8mes de calcul fiables, robustes et hautement performants.<\/p>\n<h2>R\u00e9f\u00e9rences<\/h2>\n<ul>\n<li>Bezanson, J., Edelman, A., Karpinski, S., &amp; Shah, V. B. (2017). Julia: A fresh approach to numerical computing. <em>SIAM Review<\/em>, 59(1), 65\u201398. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1137\/141000671\">https:\/\/doi.org\/10.1137\/141000671<\/a><\/li>\n<li>Euclide. (2002). <em>Les \u00c9l\u00e9ments<\/em> (trad. B. Vitrac, Vol. 1\u20134). Presses Universitaires de France.<\/li>\n<li>Harris, C. R., Millman, K. J., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., Wieser, E., Taylor, J., Berg, S., Smith, N. J., Kern, R., Picus, M., Hoyer, S., van Kerkwijk, M. H., Brett, M., Haldane, A., del R\u00edo, J. F., Wiebe, M., Peterson, P., \u2026 Oliphant, T. E. (2020). Array programming with NumPy. <em>Nature<\/em>, 585(7825), 357\u2013362. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1038\/s41586-020-2649-2\">https:\/\/doi.org\/10.1038\/s41586-020-2649-2<\/a><\/li>\n<li>Lam, P. K., Pitrou, A., &amp; Seibert, S. (2015). Numba: A LLVM-based Python JIT compiler. In <em>Proceedings of the Second Workshop on the LLVM Compiler Infrastructure in HPC<\/em> (pp. 1\u20136). Association for Computing Machinery. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1145\/2833157.2833162\">https:\/\/doi.org\/10.1145\/2833157.2833162<\/a><\/li>\n<li>McKinney, W. (2010). Data structures for statistical computing in Python. In S. van der Walt &amp; J. Millman (Eds.), <em>Proceedings of the 9th Python in Science Conference<\/em> (pp. 56\u201361). <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.25080\/Majora-92bf1921-00a\">https:\/\/doi.org\/10.25080\/Majora-92bf1921-00a<\/a><\/li>\n<li>Pedregosa, F., Varoquaux, G., Gramfort, A., Michel, V., Thirion, B., Grisel, O., Blondel, M., Prettenhofer, P., Weiss, R., Dubourg, V., Vanderplas, J., Passos, A., Cournapeau, D., Brucher, M., Perrot, M., &amp; Duchesnay, \u00c9. (2011). Scikit-learn: Machine learning in Python. <em>Journal of Machine Learning Research<\/em>, 12, 2825\u20132830.<\/li>\n<li>Virtanen, P., Gommers, R., Oliphant, T. E., Haberland, M., Reddy, T., Cournapeau, D., Burovski, E., Peterson, P., Weckesser, W., Bright, J., van der Walt, S. J., Brett, M., Wilson, J., Millman, K. J., Mayorov, N., Nelson, A. R. J., Jones, E., Kern, R., Larson, E., \u2026 SciPy 1.0 Contributors. (2020). SciPy 1.0: Fundamental algorithms for scientific computing in Python. <em>Nature Methods<\/em>, 17(3), 261\u2013272. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1038\/s41592-019-0686-2\">https:\/\/doi.org\/10.1038\/s41592-019-0686-2<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Guide acad\u00e9mique complet pour calculer la distance euclidienne en Python : impl\u00e9mentations math\u00e9matiques, NumPy, SciPy, Pandas et cas d&rsquo;usage avanc\u00e9s.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","categories":[2269,2465],"tags":[3788,4319,2960,16,4352],"class_list":["post-4671","psych_stat","type-psych_stat","status-publish","hentry","category-methodes-quantitatives","category-programmation-python","tag-distance-euclidienne","tag-machine-learning","tag-numpy","tag-psychometrie","tag-scipy"],"_links":{"self":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/4671","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat"}],"about":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/types\/psych_stat"}],"author":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4671"}],"version-history":[{"count":0,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/4671\/revisions"}],"wp:attachment":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}