{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Didacticiel Matlab\n", "\n", "Ce didacticiel aborde la plupart des fonctionnalités utilisées dans les TP de Matlab, notamment pour les TP de probas et de stats. Vous pouvez exécuter les blocs de texte et de code un par un en prenant le temps de bien les comprendre.\n", "\n", "Avant de commencer, assurez-vous que le noyau Octave est sélectionné. Pour cela, si la barre inférieure indique \"No Kernel\", cliquez dessus et choisissez \"Octave\".\n", "\n", "Une fois ce noyau sélectionné, vous pouvez lancer successivement chaque cellule au fur et à mesure de votre lecture en cliquant sur la triangle dans la barre supérieure.\n", "\n", "## 1) Définition de matrices\n", "\n", "Pour définir un **vecteur ligne** :" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "V_ligne = [1 3 5 7 9]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour définir un **vecteur colonne** :" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "V_colonne = [2; 4; 6; 8; 10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "De manière générale, on utilise **des espaces (ou des virgules) comme séparateur horizontal** et le **point virgule comme séparateur vertical**.\n", "La même règle s'applique à la définition d'une matrice. Essayez de prédire la matrice qui sera définie par l'instruction suivante avant de l'exécuter :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = [1 3 5 7 9; 2 4 6 8 10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut également construire M à partir de la **concaténation** des vecteurs définis précédemment. On pourrait penser à écrire quelque chose comme :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = [V_ligne; V_colonne]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "À l'exécution de cette ligne, une erreur de dimensions est levée. En effet, V_ligne est de taille 1x5 et V_colonne est de taille 5x1.\n", "En transposant V_colonne (V_colonne' ou transpose(V_colonne)), on résout ce problème de dimensions :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = [V_ligne; V_colonne']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comme les valeurs de M sont régulièrement espacées, il est possible d'utiliser des **plages de valeurs** avec un certain pas.\n", "Exécutez les deux instructions suivantes et identifiez à chaque fois les bornes de la plage ainsi que le pas." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Enum1 = 3:7:90" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Enum2 = 5:3:20" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Essayez de réécrire V_ligne, V_colonne et M en utilisant des plages." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V_ligne =" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V_colonne = " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M =" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Vérifiez avec les solutions données ci-dessous.\n", " **Attention à ne pas écrire V_colonne = 2:2:10'** car la transposition ne s'applique alors qu'à 10 et on obtiendrait un vecteur ligne." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V_ligne = 1:2:9\n", "V_colonne = (2:2:10)'\n", "V_colonne = transpose(2:2:10)\n", "M = [1:2:9; 2:2:10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Enfin, il est possible de définir des matrices ne contenant que des 0 ou que des 1, ou encore des matrices identités (des 1 sur la diagonale et des 0 partout ailleurs).\n", "Dans tous ces cas, il faut indiquer les dimensions de la matrice souhaitée. Si une seule dimension est donnée, elle est utilisée comme nombre de lignes et de colonnes : on obtient alors une matrice carrée." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M0 = zeros(3, 5)\n", "M1 = ones(3, 5)\n", "M2 = ones(4, 4)\n", "M3 = ones(4)\n", "Id = eye(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2) Opérations sur les matrices\n", "\n", "Il est possible d'ajouter une constante à un vecteur/une matrice :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MplusTrois = M+3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible de multiplier un vecteur/une matrice par une constante :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "troisFoisM = 3*M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible d'additionner des matrices de mêmes tailles" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MplusMplusM = M+M+M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Attention, sous certaines conditions, Matlab permet les additions entre une matrice et un vecteur s'ils ont une dimension en commun.\n", "Le vecteur est alors répliqué selon la dimension non commune pour faire la même taille que la matrice. Par exemple, les deux instructions suivantes sont équivalentes :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M + [1 3 5 7 9]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M + [1 3 5 7 9; 1 3 5 7 9]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "M est de taille (2,5) et V_ligne = [1 3 5 7 9] est de taille (1,5) donc, lors de l'addition, V_ligne est répliqué deux fois pour faire la taille de M.\n", "Vous nous déconseillons d'utiliser cette réplication propre à Matlab et nous verrons plus loin comment répliquer manuellement un vecteur ou une matrice." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le produit matriciel usuel entre M1 de taille (m,k) et M2 de taille (k,n) donne une matrice de taille (m,n).\n", "Il se fait comme suit :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M*V_colonne" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V_ligne*V_colonne" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V_colonne*V_ligne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est alors possible de répliquer un vecteur en le multipliant par un vecteur ones de taille adaptée. Par exemple, pour répliquer [1 3 5 7 9] de taille (1,5) en [1 3 5 7 9; 1 3 5 7 9] de taille (2,5), on peut faire l'instruction suivante :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ones(2,1) * [1 3 5 7 9]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Enfin, il existe la fonction **repmat** (pour réplique matrice) qui permet de répliquer une matrice un certain nombre de fois horizontalement et un certain nombre de fois verticalement pour obtenir une plus grande matrice. Par exemple :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ " repmat(M, 4, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ainsi, pour répliquer [1 3 5 7 9] en une matrice de tailles (2,5), on peut faire :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "repmat([1 3 5 7 9], 2, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible de vectoriser une matrice. Le vecteur obtenu est **la concaténation des colonnes** de la matrice." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M_vectorise = M(:)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sur des matrices de mêmes tailles, il est possible d'effectuer des **opérations élément par élément**, comme suit :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I = [200 180 170 190 155; 205 190 195 165 150; 210 215 175 155 190]\n", "Coefficients = [0.5 0.2 0.4 0.8 1; 0.4 0.2 0 1 0.9; 0.75 0.5 0.6 1 0.1]\n", "\n", "I.*Coefficients % Produit élément par élément de I et de Coefficients" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I.*I % Matrice des carrés des éléments de I" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I.^3 % Matrice de chaque élément de I élevé à la puissance 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Certaines fonctions s'effectuent sur tous les éléments d'une matrice sans qu'il soit nécessaire de le préciser avec un \".\".\n", "C'est notamment le cas des fonctions usuelles cosinus **cos**, sinus **sin**, racine carrée **sqrt**, etc :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "racineI = sqrt(I)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I - racineI.*racineI" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dans cet exemple, on remarque que l'on obtient pas une matrice entièrement composée de 0 car la précision de la machine sur les opérations flottantes est limitée. Notez la présence du facteur multiplicatif 1.0e-13." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3) Modification des éléments d'une matrice\n", "Lorsque l'on veut modifier la valeur d'un élément en particulier, une première syntaxe consiste à préciser le numéro de ligne et le numéro de colonne de l'élément :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z1 = zeros(7, 5); % Ce point-virgule en fin de ligne permet de ne pas afficher le résultat de l'instruction\n", "Z1(2, 3) = 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On remarque qu'en Matlab, les indices commencent à 1 et non à 0 comme dans de nombreux langages (C, Python...).\n", "Une deuxième syntaxe consiste à donner **l'indice absolu** de l'élément. De nouveau, on compte selon les colonnes :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z1(5) = 18" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z1(13) = 21" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe deux fonctions **sub2ind** et **ind2sub** qui permettent de convertir un indice absolu en indices relatifs (numéros de ligne et de colonne) et inversement. Il est nécessaire de donner la taille de la matrice considérée en entrée de ces fonctions :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[ligne, colonne] = ind2sub(size(Z1), 13)\n", "indice_absolu = sub2ind(size(Z1), 2, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction **ind2sub** est une fonction qui peut renvoyer plusieurs sorties : elle renvoie l'indice de ligne et l'indice de colonne. Nous donnerons d'autres exemples de ce genre de fonctions plus loin." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour modifier plusieurs éléments simultanément, il faut indiquer les indices des éléments à modifier et donner les nouvelles valeurs de ces éléments dans une matrice de taille adaptée. Nous donnons plusieurs exemples ci-dessous, prenez le temps de les comprendre :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z2 = zeros(9, 7);\n", "Z2(2, 3:7) = V_ligne" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z2(4:8, 1) = V_colonne" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z2(5:6, 3:7) = M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il est possible d'extraire une sous-matrice en indiquant les plages d'indices désirées. Par exemple :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z2(3:8, 1:5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut également indiquer un pas. Essayez de prédire ce que renvoie l'instruction suivante puis exécutez-la :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z2(2:2:6, 3:2:7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La sous-matrice obtenue est de taille (3,3). Il est donc possible de modifier tous ces éléments d'un coup en donnant les nouvelles valeurs dans une matrice de taille (3,3), comme dans l'exemple suivant. Prenez le temps de bien localiser les éléments de A dans la matrice Z2 :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = [3 4 2; 5 5 5; 9 0 3]\n", "Z2(2:2:6, 3:2:7) = A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La longueur d'un vecteur peut être obtenue par la fonction **length** :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "longueur = length(V_ligne)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'utilisation de **length** sur une matrice est déconseillé car la fonction ne retourne alors que la plus grande dimension de la matrice.\n", "\n", "Le **nombre de lignes** et le **nombre de colonnes** d'une matrice peuvent être obtenus avec **size** en faisant :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z3 = zeros(6, 4)\n", "nb_lignes = size(Z3, 1)\n", "nb_colonnes = size(Z3, 2)\n", "plus_grande_dimension = length(Z3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il existe plusieurs façons de redéfinir une ligne (ou une colonne) entière. On peut donner une plage d'indices allant de 1 à nb_lignes ou nb_colonnes :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z3(4, 1:nb_colonnes) = 99\n", "Z3(1:nb_lignes, 2) = -55" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut utiliser le symbole \":\" qui indique de considérer tous les éléments de la ligne (ou de la colonne) :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z4 = zeros(6, 4)\n", "Z4(3, :) = 11\n", "Z4(:, 4) = -33" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Enfin, il est possible d'utiliser le mot clé \"end\" à la place de nb_lignes ou nb_colonnes :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z5 = zeros(6, 4)\n", "Z5(2, 1:end) = 222\n", "Z5(1:end, 1) = 666" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour modifier simultanément plusieurs éléments, on utilise un vecteur d'indices absolus. Par exemple, pour mettre la valeur 1 aux indices absolus 2, 5, 7, 12, 13, 14, 19 d'une matrice de tailles (6,4), on utilise :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Z6 = zeros(6, 4)\n", "Z6([2, 5, 7, 12, 13, 14, 19]) = 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction **sub2ind** évoquée précédemment peut s'avérer utile pour récupérer un indice absolu à partir des numéros de ligne et de colonne d'un élément. En pratique, on n'utilise rarement ces conversions car Matlab dispose de fonctions qui permettent de s'en passer. Nous donnons un exemple ci-dessous." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Supposons que l'on dispose d'une matrice I et que l'on souhaite remplacer tous les éléments de I de valeur inférieure à un certain seuil (disons 177) par 0. L'instruction I <= 177 renvoie une matrice booléenne :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I = [200 180 170 190 155; 205 190 195 165 150; 210 215 175 155 190]\n", "I <= 177" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour récupérer les indices des valeurs de I inférieures à 177 avec **find** :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "find(I <= 177)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut alors récupérer les valeurs de I inférieures à 177 en faisant :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I(find(I <= 177))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'instruction suivante, plus épurée, renvoie le même résultat :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I(I <= 177)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ainsi, pour mettre à 0 tous les éléments de I inférieures à 177, on peut écrire :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I(I<=177) = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "qui est la version plus épurée de :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I(find(I<=177)) = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4) Fonctions utiles\n", "On peut modifier la forme d'une matrice avec la fonction **reshape** : la seule contrainte est que le nombre d'éléments total doit rester le même. À nouveau, l'ordre des éléments se retrouve dans la vectorisation de la matrice, comme illustré ci-dessous sur une matrice de taille (4,6) (donc à 24 éléments). Prenez le temps de bien comprendre les exemples ci-dessous :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "J = [200 180 170 190 155 120; 205 190 195 165 150 60; 210 215 175 155 190 160; 125 155 165 145 200 185]\n", "J1 = J(:) % Vectorisation de J\n", "J2 = reshape(J, 3, 8)\n", "J3 = reshape(J, 6, 4)\n", "J4 = reshape(J, 8, 3)\n", "J5 = reshape(J, 24, 1) % équivalent à J(:)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction **max** permet de récupérer l'élément d'un vecteur (colonne ou ligne) de valeur maximale, ainsi que son indice.\n", "Il s'agit d'une fonction qui peut renvoyer plusieurs sorties, tout comme **size**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "W = [4, 12, 3, 7, 6]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observez les deux syntaxes suivantes et identifiez les différences :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "valeur_maximale = max(W)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[valeur_maximale, indice_du_maximum] = max(W)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si l'on ne précise qu'une seule sortie, **max** ne renvoie que la valeur maximale.\n", "Pour obtenir l'indice du maximum, il faut demander deux sorties entre crochets comme dans la deuxième syntaxe.\n", "Si l'on ne souhaite se servir que de l'indice du maximum, il est possible de se passer de la sortie correspondant à la valeur du maximum avec le symbole \"~\" :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[~, indice_du_maximum] = max(W)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dans le cas d'une matrice, la fonction **max** permet de récupérer la valeur maximale de chaque colonne ainsi que son indice." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "J\n", "maxima = max(J)\n", "[~, indices_maxima] = max(J)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "De la même façon, la fonction **sort** permet de trier les valeurs par ordre croissant ('ascend') ou décroissant ('descend') et de renvoyer les indices correspondants si deux sorties sont demandées." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "W\n", "valeurs_ordre_croissant = sort(W, 'ascend') % Par défaut, sort utilise ascend s'il n'y a pas de 2ème paramètre\n", "valeurs_ordre_decroissant = sort(W, 'descend')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[valeurs_ordre_croissant, indices_ordre_croissant] = sort(W, 'ascend')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[~, indices_ordre_croissant] = sort(W, 'ascend')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut vérifier que W(indices_ordre_croissant) donne valeurs_ordre_croissant :" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "W(indices_ordre_croissant)\n", "valeurs_ordre_croissant" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La fonction **mean** renvoie :\n", "- la moyenne des éléments d'un vecteur lorsqu'elle est utilisée sur un vecteur ;\n", "- les moyennes de chaque colonne ou de chaque ligne d'une matrice lorsqu'elle est utilisée sur une matrice.\n", "\n", "Pour préciser si la moyenne doit être calculée par lignes ou par colonnes, il est nécessaire d'ajouter un deuxième argument égal à 1 (par colonnes) ou à 2 (par lignes). Par défaut, en l'absence de deuxième argument, la moyenne est calculée par colonnes (valeur par défaut : 1)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V = [2 3 5 8 12]\n", "mean(V)\n", "\n", "M = [1 3 5 7 9; 2 4 6 8 10]\n", "moyennes_par_colonnes = mean(M, 1)\n", "moyennes_par_lignes = mean(M, 2)\n", "moyennes_par_defaut = mean(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "De façon similaire, la fonction **sum** renvoie :\n", "- la somme des éléments d'un vecteur lorsqu'elle est utilisée sur un vecteur ;\n", "- les sommes de chaque colonne ou de chaque ligne d'une matrice lorsqu'elle est utilisée sur une matrice.\n", "De nouveau, pour préciser si les moyennes doivent être calculées par lignes ou par colonnes, on ajoute un deuxième argument égal à 1 (par colonnes) ou à 2 (par lignes). Par défaut, si l'on n'indique pas de deuxième argument, il est égal à 1." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "V = [2 3 5 8 12]\n", "sum(V)\n", "\n", "M = [1 3 5 7 9; 2 4 6 8 10]\n", "sommes_par_colonnes = sum(M, 1)\n", "sommes_par_lignes = sum(M, 2)\n", "sommes_par_defaut = sum(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ainsi, les moyennes peuvent être calculées soit avec **mean**, soit avec **sum** et **size**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = [1 3 5 7 9; 2 4 6 8 10];\n", "mean(M, 1)\n", "sum(M, 1)/size(M, 1)\n", "mean(M, 2)\n", "sum(M, 2)/size(M, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5) Les boucles **for**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lorsque l'on veut faire une boucle **for** en Matlab, on précise un vecteur contenant toutes les valeurs que doit prendre l'indice de boucle (i dans l'exemple donné ci-dessous). Par exemple, pour une boucle de 1 à 1000 on utilisera le vecteur [1 2 3 ... 1000] qui s'écrit plus simplement 1:1000." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "somme = 0;\n", "for i = 1:10\n", " somme = somme + i % Ajouter un ';' en fin de ligne permet d'éviter l'affichage à chaque tour de boucle\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cet exemple illustre bien l'intérêt d'ajouter des ';' en fin de ligne pour éviter l'affichage.\n", "\n", "Dans l'exemple suivant, nous souhaitons calculer une matrice C qui est la somme de deux matrices A et B.\n", "Nous montrons comment le faire de deux manières différentes :\n", "- avec une boucle **for**\n", "- matriciellement\n", "\n", "Pour chaque méthode, nous mesurons le temps d'exécution en appelant les instructions **tic** et **toc** respectivement avant et après le bloc de code dont on veut mesurer le temps d'exécution." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = rand(2000,1500);\n", "B = rand(size(A));\n", "C = zeros(size(A));\n", "\n", "tic\n", "% Avec une boucle for\n", "for i = 1:size(C, 1)\n", " for j = 1:size(C, 2)\n", " C(i, j) = A(i, j) + B(i, j);\n", " end\n", "end\n", "toc" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "A = rand(2000, 1500);\n", "B = rand(size(A));\n", "C = zeros(size(A));\n", "\n", "tic\n", "C = A + B;\n", "toc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Bien souvent, le fait d'utiliser des boucles **for** augmente les temps de calcul.\n", "Il n'est cependant pas toujours évident de se passer de ces boucles, mais nous vous demanderons de les éviter au maximum lorsqu'elles sont remplaçables par d'autres fonctions ou opérations matricielles.\n", "\n", "Pour illustrer un cas où se passer de boucle **for** n'est pas évident, nous proposons l'exemple d'une quantification d'histogramme.\n", "Nous souhaitons compter le nombre d'éléments d'une matrice dont la valeur est comprise entre 0 et 0.1, entre 0.1 et 0.2, entre 0.2 et 0.3...et entre 0.9 et 1.\n", "De nouveau, nous proposons une version avec boucle **for** et une version sans. Prenez le temps de bien comprendre les deux versions :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = rand(800, 600);\n", "\n", "Histogramme = zeros(1, 10);\n", "\n", "tic\n", "for i = 1:size(M, 1)\n", " for j = 1:size(M, 2)\n", " valeur = floor(M(i, j)*10); % pour obtenir un indice entre 0 et 9\n", " indice = valeur+1; % les indices en Matlab commencent à 1\n", " Histogramme(indice) = Histogramme(indice) + 1;\n", " end\n", "end\n", "toc" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "M = rand(800, 600);\n", "\n", "Histogramme = zeros(1, 10);\n", "\n", "tic\n", "M = repmat(M(:), 1, 10);\n", "intervalles1 = 0:0.1:0.9;\n", "intervalles2 = 0.1:0.1:1;\n", "\n", "Histogramme = sum(M >= intervalles1 & M < intervalles2);\n", "toc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le symbole **&** désigne ici le ET logique.\n", "De la même façon, on peut écrire un OU logique avec le symbole **|**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6) Exemple complet : distance moyenne entre deux points d'un cercle\n", "Nous présentons ici un exemple de programme Matlab faisant appel à différentes fonctionnalités présentées précédemment. Assurez-vous de bien comprendre chacune des lignes de code.\n", "\n", "On se propose de calculer la distance moyenne entre deux points situés sur un cercle de rayon 1.\n", "Pour cela, nous tirons aléatoirement 100 paires de points et calculons les distances entre points, paire par paire.\n", "Pour faire ce tirage aléatoire, nous utilisons la fonction **rand** qui tire des valeurs aléatoires entre 0 et 1 (selon une loi uniforme) et multiplions par 2\\*pi pour avoir des angles entre 0 et 2\\*pi et donc des points sur le cercle unité en utilisant **cos** et **sin**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nb_points = 100;\n", "\n", "thetas1 = 2*pi*rand(1, nb_points); % Pour tirer nb_points angles entre 0 et 2*pi\n", "thetas2 = 2*pi*rand(1, nb_points); % Pour tirer nb_points autres angles entre 0 et 2*pi\n", "\n", "points1 = [cos(thetas1); sin(thetas1)]; % Pour créer nb_points points sur le cercle unité\n", "points2 = [cos(thetas2); sin(thetas2)]; % Pour créer nb_points autres points sur le cercle unité\n", "\n", "distances = sqrt(sum((points1 - points2).^2,1));\n", "% (points1 - points2).^2 contient les (x2-x1)^2 sur la première ligne et les (y2-y1)^2 sur la deuxième ligne\n", "% sum(points1 - points2).^2,1) est un vecteur contenant les (x2-x1)^2+(y2-y1)^2\n", "% sqrt(sum(points1 - points2).^2,1)) est un vecteur contenant les Racine((x2-x1)^2+(y2-y1)^2), donc les distances\n", "\n", "distance_moyenne = mean(distances)\n", "\n", "4/pi % Valeur théorique à trouver" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Essayez d'augmenter la valeur de nb_points. Plus elle est grande, plus vous devriez trouver une distance moyenne proche de la distance moyenne théorique." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7) Lecture et affichage d'images\n", "\n", "En Matlab, les images sont représentées par des matrices dont chaque élément représente le niveau de gris (pour des images en noir et blanc) ou la couleur (pour des images en couleur) d'un pixel de l'image. Pour des images en niveaux de gris, les matrices associées sont bidimensionnelles et sont de taille (nb_lignes, nb_colonnes). Pour des images en couleur, les matrices associées sont tridimensionnelles et sont de taille (nb_lignes, nb_colonnes, 3) : les 3 canaux de la troisième dimension permettent d'encoder le niveau de couleur (rouge, vert ou bleu) du pixel (codage RGB).\n", "\n", "Les valeurs sont prises entre 0 et 255 inclus.\n", "\n", "À titre d'exemples :\n", "- (r = 255, g = 0, b = 0) donne du rouge vif\n", "- (r = 255, g = 255, b = 0) donne du jaune vif\n", "- (r = 128, g = 128, b = 128) donne du gris\n", "- pour des images en niveaux de gris, 0 correspond au noir et 255 au blanc\n", "\n", "Vous pouvez sélectionner une couleur et obtenir son code RGB sur le site suivant : https://htmlcolorcodes.com/fr/selecteur-de-couleur/\n", "\n", "De manière générale, les fonctions d'affichage seront déjà écrites dans les TP de probabilités et statistiques. Nous présentons donc rapidement les principales fonctions.\n", "\n", "Matlab dispose de quelques images internes.\n", "La lecture d'une image se fait avec la fonction **imread** :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I = imread('einstein.jpg')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "imagesc(I);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour l'affichage des images en niveaux de gris, Matlab utilise une palette de couleurs. Par défaut, il s'agit de couleurs allant du jaune/vert pour les niveaux de gris élevés au bleu pour les niveaux de gris faibles.\n", "Il est possible de modifier la palette de couleurs avec l'instruction **colormap** comme suit :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "colormap gray;\n", "imagesc(I);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ci-dessous, un exemple d'image en couleur. Notez que la matrice est affichée canal par canal : I(:,:,1) correspond au canal rouge, I(:,:,2) au canal vert et I(:,:,3) au canal bleu. En pratique, on n'affichera pas les matrices. Pour cela, vous pouvez ajouter un \";\" en fin de ligne.\n", "\n", "Lorsque l'on affiche des images en couleur, il n'y a pas de colormap à gérer." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I = imread('fruits.jpg'); % En mettant un \";\" après la fermeture de parenthèse, la matrice n'est pas affichée" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "imagesc(I);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8) Erreurs classiques\n", "\n", "On ne parvient pas toujours à écrire un code sans erreur du premier coup.\n", "Au travers de messages d'erreur, Matlab indique généralement le type d'erreur rencontré (problème de dimension, variable non définie...) et la ligne à laquelle se produit l'erreur.\n", "\n", "Dans cette partie, nous vous fournissons plusieurs instructions Matlab qui renvoient une erreur lorsqu'elles sont lancées. À vous de comprendre d'où proviennent les erreurs et de les corriger :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Matrice = 256*rand(320, 240)); % Matrice de nombres aléatoires entre 0 et 256" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "% On souhaite ajouter à chaque colonne de A sa colonne suivante. La dernière colonne de A reste inchangée.\n", "Matrice(:, 1:end-1) = Matrice(:, 1:end-1) + matrice(:, 1:end);" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "% On souhaite ensuite centrer les valeurs en retirant la valeur moyenne de la matrice obtenue.\n", "Matrice = Matrice - repmat(mean(meen(Matrice)), 320, 240);" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "% On souhaite mettre à 0 tous les coefficients négatifs.\n", "(Matrice < 0) = 0;" ] } ], "metadata": { "kernelspec": { "display_name": "Octave", "language": "octave", "name": "octave" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }