L'objet de ce chapitre est très similaire au chapitre précédent. Sauf que cette fois-ci, nous allons utiliser une base complète de signaux assez particulière pour recomposer le signal de température que nous avions
étudié lors du chapitre Évaluer un modèle.
Cette base est constituée de fonctions de forme sinusoïdale (cosinus et sinus).
Acquisition et visualisation des données
Comme d'habitude, commencez par importer les données. Cette fois, trois fichiers (temperatures.dat | BanqueSinus.dat | BanqueCosinus.dat) sont fournis : d'un côté les données et de l'autre une série de signaux qui vont servir de base.
data = load('temperatures.dat'); %On en profite pour regarder : plot(data,'o');
%ici BanqueSinus est un tableau %regardons la première colonne (en bleu), et la 4e (en rouge) plot(BanqueSinus(:,1),'b') hold on plot(BanqueSinus(:,4),'r') hold
off
Vous obtenez :
Visualisation de deux vecteurs de la banque de Sinus
Si vous tracez d'autres vecteurs, vous remarquerez que plus le numéro de colonne est élevé, plus les oscillations sont rapides. Vous pouvez également représenter les cosinus avec la même méthode et le résultat est similaire.
Vous remarquerez également que contrairement au chapitre précédent où l'on ne disposait que de 4 vecteurs de base, il y a cette fois-ci un très grand nombre de signaux qui serviront de base (48 cosinus et 48 sinus différents).
%Pour savoir combien de colonnes il y a dans les données: size(BanqueSinus)
ans =
96 48
Ce résultat signifie qu'il y a 48 colonnes contenant chacune 96 points.
Le nombre total (96) n'est pas un hasard. Vous remarquerez qu'il correspond au nombre de points des données expérimentales.
S'agit-il ici de sinus et cosinus quelconques ?
Évidemment la réponse est non : ces vecteurs ont été choisis soigneusement et vous verrez dans la suite du cours, dans le détail, comment ils ont été choisis.
Les signaux sinusoïdaux forment-ils une base ?
Comme dans le chapitre précédent, nous allons voir que tous ces vecteurs forment une base.
Cela n'est pas très compliqué, il suffit de tester :
%testons si le vecteur 1 et le vecteur 2 de la Banque des Sinus sont orthogonaux %dot est une fonction intégrée de matlab qui calcule le produit scalaire de deux vecteurs (c'est en pratique la même chose que la fonction prodScal que vous aviez
construite dans le tuto précédent) dot(BanqueSinus(:,1),BanqueSinus(:,2))
Auquel Matlab répond :
ans = -5.1051e-18
Ce qui suggère que ces deux vecteurs sont bien orthogonaux (ce nombre est négligeable devant 1). Il ne nous reste plus qu'à tester les 9119 autres combinaisons de vecteurs possibles restantes...
Autant vous le dire, je vous déconseille de le faire à la main. Nous allons donc le faire de façon automatique. Voici une implémentation possible qui utilise deux boucles imbriquées.
% on met tous les vecteurs dans une grosse matrice TousLesVecteurs = [BanqueCosinus BanqueSinus]; %on initialise un tableau "orthogonalite" qui contiendra les valeurs des produits scalaires orthogonalite = []; % [] signifie tableau vide for
i = 1:96 for j = 1:96 if i ~= j % ~= signifie "different de" on ne teste pas l'orthogonalite si ce sont les même vecteurs
v1 = TousLesVecteurs(:,i); v2 = TousLesVecteurs(:,j); orthogonalite = [orthogonalite dot(v1,v2)]; % on rajoute
au tableau "orthogonalite" la valeur du produit scalaire qui nous intéresse end end end
Vous pouvez explorer les valeurs contenues dans le tableau orthogonalite, et vous verrez que toutes les valeurs sont nulles. Vous pouvez le vérifier en comptant le nombre de fois où le produit scalaire
est plus petit que \( 10−6 \) :
sum(orthogonalite < 1e-6)
Auquel Matlab répond :
ans = 9120
Ce qui est aussi la taille totale du tableau orthogonalite.
Nous sommes donc rassurés, tous les vecteurs sont orthogonaux entre eux (encore une fois un miracle ?). Il s'agit bien d'une base. Je vous laisse vérifier qu'ils sont tous également tous unitaires (une seule boucle suffira).
Recomposition du signal
Maintenant que l'on est certain d'avoir une base orthonormée, il est garanti que nous allons pouvoir reconstituer n'importe quel vecteur de taille 96. En particulier le vecteur correspondant aux données expérimentales
(la série de température).
Profitons au passage de la recomposition pour stocker la valeur des projections sur chaque vecteur de base (les composantes).
N = length(data); % ici N = 96 normalement coefficients = [];% on initialise un tableau pour mettre tous les composantes recomp = zeros(N,1); % on initialise un vecteur recomposition
%Boucle sur tous les vecteurs de base for k
= 1:N vectBase = TousLesVecteurs(:,k); % on selectionne un vecteur coef = dot(data,vectBase); % on calcule la composante coefficients = [coefficients coef]; % on stocke la composante
recomp = recomp + coef*vectBase; % on ajoute au vecteur recomposé la bonne proportion du vecteur de base end
% on représente la recomposition en rouge, et les données en noir plot(recomp,'r') hold on plot(data,'k+') hold
off legend({'Signal recomposé' 'Données'})
Vous obtenez :
Nous avons pu parfaitement recomposer le signal d'origine avec la décomposition sur des sinus/cosinus
Peut-on interpréter les composantes ?
Alors certes, la recomposition a donné un excellent résultat, mais peut-on essayer de comprendre un peu mieux ce qui s'est passé ?
Pour cela, jetons un œil à la liste des composantes. Vous pouvez par exemple la représenter avec plot(coefficients).
Vous remarquerez que la plupart des coefficients sont faibles, sauf peut-être le 1er, le 5e, le 9e et le 52e.
Le premier coefficient vaut ainsi 197.08. Cela signifie que pour recomposer la série de température, il faut ajouter 197.08 fois le tout premier vecteur.
Regardons à quoi cela correspond:
plot(197.08*TousLesVecteurs(:,1),'r'); % on représente la contribution du premier vecteur hold on plot(data,'k+') hold off
Vous obtenez :
La contribution du premier vecteur correspond à un ajout de valeur moyenn
Le tout premier vecteur est en fait un vecteur tout plat (il s'agit en fait de cos(0×x), un cosinus de fréquence nulle). La contribution du premier vecteur (en rouge) tombe pile sur la valeur moyenne du signal à recomposer.
Ajoutons maintenant la composante numéro 5 (cette composante vaut coefficients(5), soit 20.059 d'après Matlab), que nous avons remarqué précédemment :
plot(197.08*TousLesVecteurs(:,1)+20.059*TousLesVecteurs(:,5),'r'); % on représente la contribution du premier vecteur hold on plot(data,'k+') hold off
On rajoute la composante numéro 5, qui est une composante qui oscille à la même fréquence que le signal d'origine
Si vous continuiez à rajouter les composantes suivantes vous vous rapprocheriez de plus en plus du signal original.
Ici le signal de départ était lui-même oscillant. Et il paraît donc naturel de décomposer ce signal sur une base oscillante, les sinusoïdes.
Mais puisque la base que nous utilisons est orthonormée, il faut bien comprendre que n'importe quelle forme de signal pourra être recomposée grâce à cette base, y compris des formes de signaux pas du tout oscillantes.
Vous pouvez aussi regarder cette petite animation qui peut-être vous aidera à visualiser un peu mieux ce que l'on peut faire avec une décomposition en sinusoïdes.
Conclusion
Dans cette partie, nous avons vu :
ce qu'était un signal au sens physique/mathématique
comment mettre des nombres dessus
comment le comparer à d'autres signaux
comment le recomposer à partir d'une base
Dans le chapitre suivant, vous verrez ce que l'on entend par représentation fréquentielle d'un signal. Mais avant d'y passer, je vous invite à tester vos connaissances avec le quiz sur la manipulation du signal 1D.