expérimentation, modélisation, et simulation en psychologie
Post on 05-Jan-2017
238 Views
Preview:
TRANSCRIPT
!
Fabien Mathy, Mustapha Chekaf, Lucie Laurent
Expérimentation, Modélisation, et Simulation en Psychologie
RÉSUMÉCe manuel décrit toutes les étapes de l'expérimentation en psychologie, depuis la manipulation des facteurs, jusqu'à l'analyse statistique et la modélisation des données, en passant par la création automatisée de stimuli et la présentation informatisée des stimuli. L'objectif principal de ce manuel est de montrer l'intérêt des logiciels pour automatiser diverses étapes de l'expérimentation pour lesquelles des opérations peuvent rapidement s'avérer répétitives. Nous insistons sur les nombreuses vertus de MATLAB et de la psychToolbox (i.e., un module de MATLAB), mais nous décrivons également SPSS, Excel et E-Prime. Grâce à des algorithmes simples, nous montrons par exemple comment compiler des fichiers de données (au lieu d'ouvrir les fichiers un par un pour faire des copier-coller), générer des stimuli (au lieu de les dessiner un par un dans un logiciel de dessin), transformer et recoder des tableaux de données. La modél isat ion en psychologie consiste à déterminer si un modèle est capable de s'ajuster aux données, en faisant varier ses paramètres. Un second objectif est de montrer que l 'a lgor i thmique n'est pas seulement ut i le mais indispensable pour modéliser des données.
DEUX CHAPITRES OFFERTS DANS CETTE VERSIONhttp://fabien.mathy.free.fr/
Créer, Importer, transformer,
compiler, restructurer, agréger,
et analyser des données
Expérimentation, Modélisation, et Simulation en psychologie
Fabien Mathy, Mustapha Chekaf, Lucie Laurent
Table des matières (En construction)
Avant-propos ....................................................................................................................................1!
Expérimentation ...............................................................................................................................3!
Chap 1. Principes d'organisation d'une expérimentation et logique expérimentale .....................3!
Chap 2. Construction de conditions expérimentales par tirage au sort ou permutations ...........11!
Chap 3. Création informatisée de stimuli...................................................................................18
Chap 4. Expérimenter avec la Psychophysics toolbox et E-Prime Analyse & modélisation ................................................................. Error! Bookmark not defined.!
Chap 5. Importer, transformer, compiler, restructurer et agréger des données.................. Error!
Bookmark not defined.!
Chap 6. Des figures complexes et originales .............................Error! Bookmark not defined.
Chap 8. Principes de la modélisation
Chap 9. Modélisation et simulation
Chap 10. L'ajustement du modèle aux données Références Bibliographiques..........................................................Error! Bookmark not defined.!
Annexes ..........................................................................................Error! Bookmark not defined.!
ANNEXE 1. Initiation à la programmation sous MATLAB ..... Error! Bookmark not defined.!
Chapitre à compléter
Chapitre 4. Expérimenter avec la Psychophysics toolbox et E-Prime (Partie sur la
Psychtoolbox à compléter)
Chapitre non écrit
Chapitre 7. L'analyse statistique avec la Statistics toolbox
1
Avant-propos
Objectifs
Ce manuel décrit toutes les étapes de l'expérimentation en psychologie, depuis la manipulation des facteurs,
jusqu'à l'analyse statistique et la modélisation des données, en passant par la création automatisée de stimuli
et la présentation informatisée des stimuli. L'objectif principal de ce manuel est de montrer l'intérêt des
logiciels pour automatiser diverses étapes de l'expérimentation pour lesquelles des opérations peuvent
rapidement s'avérer répétitives. Nous insistons sur les nombreuses vertus de MATLAB et de la
psychToolbox (i.e., un module de MATLAB), mais nous décrivons également SPSS, Excel et E-Prime.
Grâce à des algorithmes simples, nous montrons par exemple comment compiler des fichiers de données
(au lieu d'ouvrir les fichiers un par un pour faire des copier-coller), générer des stimuli (au lieu de les
dessiner un par un dans un logiciel de dessin), et transformer et recoder des tableaux de données. La
modélisation en psychologie consiste à déterminer si un modèle est capable de s'ajuster aux données, en
faisant varier ses paramètres. Un second objectif est de montrer que l'algorithmique n'est pas seulement
utile mais indispensable pour modéliser des données.
Atouts de la programmation
Utiliser des logiciels standards en psychologie tels qu'E-Prime et SPSS pour expérimenter puis analyser les
données peut rapidement présenter une limite. Si vous visez une expérimentation simple et une analyse
simple des données, les logiciels habituellement utilisés en psychologie (e.g., E-Prime, Excel, SPSS,
Statistica) ont une utilité indéniable et peuvent être suffisants pour remplir vos objectifs. MATLAB peut
également s'avérer -au final- un outil très simple d'utilisation pour expérimenter et analyser vos données,
mais le temps requis pour apprendre son langage peut être un frein. Il peut donc apparaître que son
apprentissage n'est pas nécessaire si les logiciels précédemment cités semblent suffire. Néanmoins, notre
conseil est de faire le choix d'apprendre à programmer, car la connaissance d'un langage de programmation
de haut niveau tel que MATLAB permet de développer l'imagination et d'envisager des expérimentations et
des analyses a priori insoupçonnables. MATLAB est une façon de décupler votre créativité dans le
domaine de la recherche.
Sur le plan de l'efficacité, MATLAB est également un atout. Programmer une analyse de données avec
MATLAB présente l'intérêt de pouvoir refaire l'analyse en un seul click si besoin. Après avoir spécifié une
liste de commandes visant à enchaîner les différentes étapes de l'analyse descriptive, les étapes de la
transformation des données, et les étapes de l'analyse inférentielle, on dispose d'un programme réutilisable.
Imaginons qu'un dossier contienne 50 fichiers correspondant aux données de 50 participants. Un
programme peut automatiquement lister les fichiers, créer une variable N = 50, faire un histogramme des
performances (les temps de réponse par exemple), transformer les temps de réponse par un logarithme pour
éviter leur distribution asymétrique et augmenter la puissance des tests inférentiels qui vont suivre, etc.
Toutes ces étapes de programmation mises bout à bout peuvent correspondre à autant d'étapes avec un
logiciel de type SPSS. Cependant, en cas de modification des données, MATLAB présente l'énorme
avantage qu'il suffit de relancer le programme d'un seul click de souris (puisqu'il est déjà fait) pour
reproduire la même séquence d'analyses, alors qu'SPSS requiert de refaire chacune des étapes de l'analyse1.
Repasser par toutes les étapes de l'analyse en cliquant à nouveau dans les menus peut être laborieux et
chronophage. Pourtant, reconduire une analyse de données est assez fréquent, pour des raisons diverses : 1)
on réalise après coup qu'un fichier présente des données aberrantes car le participant semble ne pas avoir
compris la consigne et montre des performances non représentatives de l'échantillon; le participant ne peut
plus faire partie de l'analyse 2) l'analyse manque de puissance, et on souhaite augmenter la taille de
l'échantillon 3) on souhaite conduire la même analyse avec un échantillon différent (e.g., des enfants à la
place d'adultes) quelques mois plus tard. Quel que soit le cas, il suffira de mettre à jour le dossier de
données afin que MATLAB récupère les nouvelles données, qu'il mette à jour automatiquement la variable
N pour appliquer l'ancien programme aux nouveaux fichiers, et qu'il conduise l'analyse à terme, en
produisant tout au long du processus les tableaux, les graphes, et les analyses statistiques. La planification
de l'analyse, l'enchaînement logique des analyses, et l'ensemble des paramètres esthétiques des tableaux et
1 A moins de connaître le langage SYNTAX, permettant également de lister une suite de commandes, mais avec beaucoup moins de
libertés que MATLAB.
2
des figures sont conservés. Au contraire, SPSS requiert une nouvelle planification de l'ensemble des
analyses (on ne se souvient plus nécessairement de l'ordre dans lequel on a cliqué dans les divers menus), et
SPSS oblige à double-cliquer sur chacune des nouvelles figures pour les éditer (e.g., transformer des barres
colorées en barres hachurées, changer l'échelle des axes pour améliorer les proportions, rajouter les barres
d'erreurs, etc.). Programmer sous Matlab peut prendre une journée, ce qui n'est pas nécessairement plus
rapide qu'avec SPSS. L’avantage accordée ici à l’utilisation de matlab peut donc se comprendre aisément
par le fait que la moindre modification des données requiert une journée de plus avec SPSS, mais
seulement une seconde de plus avec MATLAB.
Un second exemple est lié à l'application de règles pour recoder des données. On souhaite par exemple
créer après coup une nouvelle variable afin de recoder une condition expérimentale. Cette variable
prendrait par exemple la valeur 1 (signifiant que la condition est réussie) si le sujet a appuyé sur la touche x
à l'essai n, après avoir appuyé sur la touche y à l'essai n-1, uniquement lorsque le stimulus z a été affiché
dans la partie nord de l'écran et uniquement lorsque le temps de présentation était inférieur à 100 ms. Cette
opération est difficile sans une recherche programmée permettant de comparer les données sur des lignes et
des colonnes différentes. Pour donner un dernier exemple, lorsqu'on souhaite trouver les paramètres d'un
modèle nouveau pour l'ajuster au mieux aux données, il est parfois nécessaire de lire un tableau de données
des milliers de fois pour calculer la meilleure adéquation du modèle aux données. Cette méthode n'est pas
possible avec un logiciel de statistiques classique dans lequel sont répertoriées des procédures classiques
opérant sur un tableau le plus souvent en une seule passe. Matlab vous permettra de trouver des solutions
efficaces à ce type de difficultés.
3
Expérimentation
Chap 1. Principes d'organisation d'une expérimentation et logique expérimentale
Les conseils donnés ici relèvent de généralités qui pourront être complétées par une lecture du chapitre 1 de
Rey (2012). Nous commençons par définir simplement des notions fondamentales telles que variable
indépendante, randomisation, consentement éclairé, etc. Nous terminons par un exposé sur les plans
expérimentaux.
Généralités
L'objectif d'une expérimentation est de déterminer si la manipulation d'une variable affecte une autre
variable et si oui, dans quelle mesure. On distingue donc la simple présence d'un effet expérimental de la
taille de cet effet (un médicament peut provoquer significativement plus de maux de tête, malgré le fait
qu'on observe que quelques dizaines de maux de tête supplémentaires sur des milliers de patients). La
significativité tient à une réponse binaire (oui, ou non, l'effet est présent), et la taille de l'effet relève de
l'indication d'un pourcentage (e.g., 5% d'infarctus supplémentaires dans la condition Dosage 1cc) ou d'un
ratio (deux fois plus de suicides dans telle condition). On dit qu'un effet expérimental est détecté dès lors
que le test statistique est significatif. Sans cela, la différence de résultats observée entre les conditions
expérimentales risque de refléter uniquement des variations insignifiantes dues au hasard. Habituellement,
il n'est pas conseillé de relever une "tendance" non significative (e.g., il y a un peu plus d'infarctus avec le
Dosage 1cc), car cette tendance a une chance équivalente en théorie d'être inversée par le même fruit du
hasard (e.g., il y a un peu plus d'infarctus avec le Dosage 2cc). Si on souhaite montrer que l'effet est avéré
pour le Dosage 1cc, il faut augmenter la taille de l'échantillon. De même, on ne calcule la taille de l'effet
que si l'effet est significatif. La taille de l'effet est un indicateur fondamental. Un médicament peut avoir un
effet secondaire préjudiciable significatif sur les maux de tête sans que cet effet soit de taille importante.
Par exemple, la différence de 30 migraines supplémentaires (dans le groupe médicament sur un échantillon
de 2000 personnes divisés en 1000 personnes ayant subi la condition Médicament dont 130 ont ressenti une
migraine dans l'heure qui suit la prise du médicament, contre 100 seulement dans le groupe de 1000
participants Placebo) produit une différence statistiquement significative permettant de rejeter l'hypothèse
d'absence de lien entre la prise de médicament et la présence de migraines, mais l'effet avec un tel
échantillon de départ est mesuré. L'effet serait double si il y avait une différence de 30 migraines sur un
échantillon de départ deux fois plus petit. Ce point sur la significativité et sur la taille des effets est
développé dans le chapitre 7.
L'expérimentation doit être réplicable et l'objectif premier de la section Méthode d'un rapport scientifique
est d'indiquer tous les détails du protocole expérimental permettant à quiconque de reconduire
l'expérimentation à l'identique afin de répliquer les résultats. La réplication des résultats est d'ailleurs
devenu un sujet houleux en psychologie depuis 2012 et de nombreux chercheurs, associations et journaux
invitent de plus en plus à considérer la réplicabilité des données comme un point central en psychologie
(Pashler et Harris, 2012; Pashler et Wagenmakers, 2012).
Nous résumons ici le chapitre "Controlled Experiments de Cairns et Cox 2008. Pour procéder à une
recherche scientifique, après avoir posé une problématique (i.e., une question), on formule une hypothèse
(une réponse à la question, ce qui se traduit par la prédiction d'un effet). L'hypothèse opérationnelle est la
description plus précise de la manière dont la réponse va s'appliquer à une expérimentation donnée ; c'est
une prédiction de résultats dans un contexte expérimental donné. Il faut avoir à l'esprit que les résultats
scientifiques sont analysés grâce aux statistiques et que les statistiques sont pour la plupart limitées au test
de rejet de l'hypothèse nulle (à moins d'avoir une formation très poussée sur les statistiques plus complexes,
telles que celles relatives au théorème de Bayes; e.g., Wetzels, Raaijmakers, Jakab, et Wagenmakers,
2009). L'hypothèse nulle étant une égalité, votre hypothèse, pour être vérifiable, doit généralement prédire
une différence entre les modalités du facteur expérimental (e.g., médicament vs placebo). Une statistique
permettant de tirer la conclusion qu'on rejette l'hypothèse nulle avec 5% de chance de fausse alarme (p <
.05) signifie simplement que 5% du temps, un résultat similaire imputable au hasard pourrait être trouvé.
Comme ce pourcentage est faible (le hasard produisant rarement un tel résultat), on fait l'inférence
inductive que notre résultat n’est probablement pas dû à l'effet du hasard, mais à l'effet de la manipulation
4
du facteur. Pour rappel, le facteur, ou variable indépendante, est la variable manipulée et la variable
dépendante est celle mesurée. Le meilleur moyen de s'en rappeler est de considérer que de la même façon
que y = f(x), VD = f(VI), signifiant que la variable dépendante dépend de la variable indépendante.
Pour résumer comment planifier une expérimentation, un bon conseil est d'imaginer par anticipation
l’analyse statistique de l'expérimentation. Commencez par exemple à écrire le rapport scientifique en
laissant des blancs pour les analyses statistiques, et surtout, tracez à la main la figure que vous souhaiteriez
obtenir pour administrer une preuve visuelle de la validité de votre hypothèse principale. Un second conseil
concerne la simplicité. Par exemple, les variables modératrices ou facteurs secondaires sont souvent un
caillou dans une chaussure, car le lecteur s'attend à ce que vous en fassiez l'analyse. Ces variables
compliquent la rédaction d'un rapport et imposent le calcul d'interactions complexes entre facteurs, parfois
ininterprétables. Contrairement aux croyances, il vaut mieux viser une expérimentation simple apportant
une explication simple. C'est une manière de suivre le principe du rasoir d'Occam, qui consiste à considérer
que les explications les plus simples sont les meilleures.
Concernant la variable indépendante, il faut prendre soin qu'elle ne se confonde pas avec une autre variable.
En constituant par exemple deux groupes de sujets pour conduire une expérimentation papier/crayon dans
une salle afin de tester l'hypothèse que les sujets ont de moins bons résultats au test lorsqu'ils composent au
soleil (peu importe l'absurdité de cette hypothèse), il ne faut pas installer les 25 premiers arrivant à l'ombre
et les 25 derniers au soleil, car vous sélectionnez en même temps la diligence des 50 participants. Les 25
premiers participants planifiant mieux leur temps, étant peut-être plus sérieux, etc., l'ordre d'arrivée pourrait
expliquer les meilleures performances au test de ceux s'étant installé à l'ombre. L'ordre d'arrivée se confond
alors avec l'effet du soleil. Dans une expérimentation, les autres variables que celles manipulée sont censées
être randomisées ou maintenues constantes. Si le groupe est constitué de 50 étudiants d'âge proche, l'âge est
considéré comme constant. S'il y a autant de filles que de garçon dans chacun des groupes, le facteur genre
est randomisé (le hasard ayant réparti équitablement les filles et les garçons dans les groupes). Le mieux,
pour prévenir tout effet parasite, est de varier les moments où les expérimentations sont conduites afin
d'éviter des variables chronobiologiques, de varier les expérimentateurs (ne surtout pas allouer un
expérimentateur par condition expérimentale, au risque que l'expérimentateur induise un effet sur un des
groupes), et de travailler en aveugle (l'expérimentateur ne doit pas connaître les effets attendus des
conditions expérimentales, de sorte à limiter une éventuelle induction inconsciente d'effet). D'autres effets
(d'ordre, de rang), plus complexes, sont décrits dans la partie "Plans expérimentaux".
Pour construire une expérimentation robuste, il est nécessaire d’en contrôler la mesure. Nous
recommandons vivement la méthode algorithmique. Par exemple, en programmant une expérimentation on
peut procéder à des tirages au sort équilibrés. Ensuite, il faut conduire une expérimentation pilote, ainsi
qu’une analyse préliminaire des données. Il peut apparaître à ce moment que des données sont mal écrites
ou non recouvrables après coup, ce qui peut limiter la portée des résultats. Un dernier conseil est de tester
l'expérimentation en conditions extrêmes, par exemple avec des enfants préscolaires ou avec un singe si
vous en avez un sous la main. Ces énergumènes risquent bien de cliquer un peu partout, d'appuyer
longuement sur des touches, en bref, ils risquent de produire toutes sortes d'imprévus dans l'enregistrement
des réponses (par exemple, deux temps de réponse sont écrits dans le fichier, car la touche a été appuyée
longuement et a généré une auto-répétition). Ainsi, vous pourrez sécuriser l'environnement de votre
expérimentation en paralysant par exemple des événements non souhaités (clicks, appuis de touche, clicks
non précis sur le plan spatial). Par exemple, il est préférable de prévoir la possibilité d'un double click opéré
par réflexe (le sujet peut s'avérer plus anxieux que prévu dans un contexte expérimental) et annuler
l'enregistrement du second click, au risque d'avoir des données contaminées. L'expression "Garbage in,
Garbage out" ? Elle fait allusion à l’idée que si vos données ne sont pas bonnes, il est probable que votre
analyse ultérieure ne vaille pas grand chose non plus.
Participants
Le premier point concerne l'échantillonnage de participants représentatifs d'une population donnée. Il est
vrai qu’en pratique, les psychologues expérimentent très souvent avec des étudiants en psychologie. Ces
étudiants ne sont représentatifs ni des autres étudiants, ni des non-étudiants, mais on considère que cet
échantillon biaisé permet néanmoins des comparaisons entre articles scientifiques assez fiables. Dans tous
5
les cas, les conclusions doivent être tirées avec circonspection. Ensuite, il faut déterminer la taille
approximative de l'échantillon pour savoir si l'expérimentation est faisable avec les moyens du laboratoire
dans les temps impartis. Ce calcul se fait sur la base de résultats antérieurs : si un effet similaire à celui
qu'on souhaite trouver a nécessité une centaine de sujet avec une significativité minimale (e.g., p < .05), un
échantillon de taille similaire est certainement requis. Pour ce type de calcul, nous invitons à utiliser
STATISTICA et son module de calcul de puissance qui permet de calculer la taille d'un échantillon requis
pour un type de résultat donné. STATISTICA permet de déterminer par exemple combien il faut de sujets
par groupe pour obtenir une différence significative de 3 points de QI connaissant la moyenne et l'écart-
type des QI).
Un point crucial est la compréhension des instructions par le participant. Il ne faut pas hésiter à utiliser un
double format, c'est-à-dire présenter la tâche oralement et visuellement (à l'aide de captures d'écran par
exemple), proposer un entraînement avec le clavier ou les boutons réponse, vérifier si les performances à la
tâche d'entraînement sont valables avant de commencer l'expérimentation. La robustesse des données est
également déterminée par la compréhension de la tâche par le participant.
Un dernier point est qu'il faut adapter le temps de passation aux sujets humains. D'après notre expérience,
des expérimentations durant plus de 30 minutes (instruction et debriefing non inclus) devraient être évitées,
à moins de les conduire en plusieurs sessions.
Noter dans un cahier toutes les conditions expérimentales et ce qui est rapporté par les participants, car les
données, souvent analysées plusieurs mois plus tard nécessitent parfois quelques explications (un sujet qui
abandonne à tel moment, un sujet qui dit ne pas avoir compris telle ou telle partie de l'expérimentation, un
sujet qu'on soupçonne être légèrement alcoolisé), le fait que deux participants ont reçu par inadvertance le
même numéro de condition expérimentale, etc.
Lieu et conditions
Privilégier un environnement calme, téléphones portables éteints, dans des espaces confinés (type box), en
passation individuelle de préférence (au risque de voir un étudiant trépigner d'impatience lorsqu'il attend
son camarade, qui au final se comportera également avec plus d'impatience, par exemple de façon plus
impulsive). Les expérimentations à distance sur internet existent, éventuellement défrayées (e.g., avec
l'outils mechanical turk surtout utilisé aux Etats-Unis), mais l’application des trois recommandations justes
mentionnées risquent de ne plus pouvoir être respectées avec certitude.
Consentement éclairé
Il est toujours utile de contractualiser une expérimentation avec un participant. C'est un point d'éthique qu'il
faut respecter et qui doit prendre en compte trois éléments (op. cit., Cairns et Cox, 2008) : 1) La
vulnérabilité du participant 2) le consentement éclairé et 3) la confidentialité des données. Utiliser un
formulaire de consentement éclairé permet d'informer rigoureusement, ce que la communication orale
néglige parfois. Pour informer le participant des multiples raisons pour lesquelles il lui est possible de
mettre fin volontairement à sa participation sans avoir à se justifier, pour donner les informations
nécessaires concernant la méthode, pour indiquer les objectifs et la durée de l'expérimentation, voici un
modèle simple de formulaire qui peut être utilisé pour demander l'accord du participant :
FORMULAIRE DE CONSENTEMENT ÉCLAIRÉ POUR EXPÉRIMENTATION Nom : Prénom : Date : Le laboratoire xxx me propose de participer à une expérimentation en psychologie. Je reconnais avoir reçu(e) toute information souhaitée, simple et intelligible concernant le déroulement de l!expérimentation et sa durée approximative. J!ai également été prévenu(e) que je pouvais arrêter l!expérimentation à tout moment, sans avoir à me justifier, si pour une raison ou une autre, l!expérimentation ne me convient pas.
6
Je reconnais avoir été prévenu(e) que les résultats seront anonymés avant d!être
analysés, et que les résultats pourront faire l!objet d!une publication scientifique.
Je reconnais avoir participé volontairement à l!expérimentation, qu!elle que soit sa
rémunération.
Signature
Une fois l'expérimentation terminée, un débriefing peut s’avérer intéressant et nourrir la curiosité de
certains participants quant à l’expérience qu’ils viennent de passer. Un temps d’échange doit donc être
possible pour échanger autour des théories, des hypothèses, et des résultats attendus. L’expérimentation
fournit un temps d’échange légitime avec les participants et il est profitable de partager avec eux des
connaissances, car ces mêmes participants peuvent avoir des explications intéressantes à donner de leur
comportement. C'est très utile d'avoir un feedback informel des participants chez qui l'introspection rejoint
parfois les intuitions scientifiques, ou vice-versa. Prévoir des créneaux trop serrés peut être assimilé à de la
désinvolture de la part de l'expérimentateur vis-à-vis des participants volontaires. Il est aussi parfois utile de
repréciser même si cela a été fait avant l'expérimentation que les données individuelles ne sont pas un
centre d'intérêt, au contraire des résultats plus généraux, et que les données sont recodées afin d'être
anonymées.
Rappel introductif sur la terminologie des plans expérimentaux
La formalisation des plans expérimentaux a pour objectif de décrire la structure d'un plan expérimental
(the design of an experiment). La structure du plan décrit l'organisation des conditions expérimentales
(autrement appelées traitements expérimentaux; experimental conditions/treatments) associées à des
groupes de sujets. Dans un plan d'expérience, on peut distinguer :
- les mesures répétées (repeated measures or within-subject designs) : les mêmes sujets passent plusieurs
conditions expérimentales). Exemple : une étude longitudinale (longitudinal study).
- les mesures couplées (randomized blocks designs) : n blocks de k sujets sont appariés en raison d'une
ressemblance et assignés aléatoirement à k conditions expérimentales; il y a donc nk sujets différents, mais
théoriquement seulement n et k sources de variations. Par exemple, on peut apparier les sujets sur leur QI.
D'un point de vue pratique, les mesures couplées sont assimilées à des mesures répétées lorsqu'un test
statistique est appliqué. Cette organisation réduit à la fois la grande variance propre aux plans indépendants
et les problèmes d'ordre de passation des plans répétés. En revanche, l'organisation est aussi coûteuse en
sujets que le plan indépendant et la procédure d'appariement peut être coûteuse en temps.
- les mesures indépendantes (independant measures, randomized groups designs, or between-subject
designs). Exemple : une étude transversale (cross sectional study).
- les plans complexes, dans lesquels on peut inclure les plans complètement indépendants ou les mesures
complètement répétées à plusieurs facteurs, et les plans partiellement répétés (autrement appelés plans
mixtes; mixed designs).
Le plan conditionne le choix des tests statistiques et l'organisation du tableau de données en vue de son
traitement par un logiciel statistique. Pour qu'un plan soit valide, l'expérimentateur doit 1) procéder à une
répartition aléatoire des sujets dans les groupes, 2) appliquer un contrebalancement (counterbalancing),
une permutation (permutation), ou une aléatorisation (ou randomisation; randomization) des ordres de
passations, afin de contrôler les ordres de passation (ces trois notions sont développées plus loin dans le
Chapitre 2) et 3) contrôler les variables non manipulées, soit en en les maintenant constantes (matching),
soit en garantissant que leurs modalités sont mixées par un échantillonnage (sampling) correct des sujets.
Certaines expériences demandent des soins supplémentaires pour contrôler les effets liés à
l'expérimentateur (organisation en simple ou double aveugle, etc.) et les effets liés aux sujets (volonté de
contribuer positivement à l'expérimentation, qu'on peut traduire par demand characteristics, un phénomène
qui biaise les résultats car le participant souhaite "bien faire" en interprétant les objectifs de
l'expérimentation, au lieu de se comporter naturellement).
7
Parmi les conditions expérimentales, on peut distinguer parfois une condition contrôle, qui est la
condition dans laquelle le facteur intervient le moins. Lorsque le facteur est réduit à néant, la condition
contrôle peut s'appeler condition témoin.
On peut distinguer plusieurs formalisations de base concernant les plans expérimentaux2.
1) Plans simples à mesure répétées. Ils sont formalisés par un croisement. Par exemple : S4 A3.
Dans ce cas, chaque sujet est soumis à trois conditions expérimentales du facteur A. L'indice 3
indique le nombre de modalités (the number of levels of treatment) du facteur. Le facteur sujet est
un facteur dont les modalités sont les sujets, ce qui est logique puisque chacun des sujets est
différent.
Exemple de tableau pour S4 A3
a1 a2 a3
s1 X X X
s2 X X X
s3 X X X
s4 X X X
Notes. i) Une croix indique qu’une mesure est effectuée. ii) Il y a un tableau par VD.
2) Plans simples à mesure indépendantes. Formalisés par un emboîtement. Par exemple : S2<F3>.
Chaque sujet est soumis à une condition expérimentale. Il faut par conséquent 3 fois plus de sujets
pour obtenir le même nombre d'observations que dans un plan répété. Si le plan est équilibré, les
sujets sont divisés aléatoirement en 3 groupes de 2 sujets. Dans la plupart des manuels, on
considère par convention que S2<F3> signifie qu’il y a 2 sujets par groupe et 6 au total en
multipliant l'indice 3 par l'indice 2. De mon point de vue, l’écriture S6<F3> serait préférable car
elle respecte la notion de divisibilité des 6 sujets dans les 3 groupes et indique le nombre correct
de modalités du facteur sujet (cf. Mathy, 2006). On dit que les sujets sont emboîtés dans le facteur
F. La structure d'emboîtement distingue le facteur emboîté du facteur emboîtant de la manière
suivante : emboîté<emboîtant>. Par définition, chaque modalité du facteur emboîté correspond à
une et une seule modalité du facteur emboîtant, l'inverse n'étant pas vrai.
Exemple de tableau pour S2<F3>
a1 a2 a3
s1 X
s2 X
s3 X
s4 X
s 5 X
s 6 X
Ou, si on utilise une variable catégorielle (comme requis dans SPSS) :
Groupe Mesure
s1 a1 X
2 Cette formalisation de Rouanet et Lépine des années 70 est franco-française et n'est pas utilisée dans les articles
scientifiques internationaux. Elle n'est donc pas indispensable, mais elle est très formatrice et couramment utilisée en
France dans un contexte pédagogique (Mathy, 2006).
8
s2 a1 X
s3 a2 X
s4 a2 X
s 5 a3 X
s 6 a3 X
3) Plans complexes. Cette classe inclut les plans factoriels (exemple à trois facteurs : les sujets sont
soumis à une seule des k k' k'' conditions possibles : S<Ak Bk' Ck''> ; k k' k'' factorial
design or k k' k'' between-subject experiment), les mesures complètement répétées
(S Ak Bk'), dans lesquelles les sujets passent chacune des k k' conditions expérimentales
résultant de la combinaison des 2 facteurs. On trouve également l'ensemble des plans mixtes dont
l'exemple le plus simple est le plan split-plot. Cette dernière dénomination évoque
l'expérimentation agronomique (split = diviser, plot = parcelle). Dans l'exemple S2<A3> B3, il y a
6 sujets appartenant à trois groupes de 2 sujets d'âges différents, soumis chacun à trois conditions
expérimentales.
Dénomination des groupes
Tout terme numéroté doit porter une majuscule pour respecter les normes de l'APA, l'American
Psychological Association (e.g., Groupe 1, Groupe 2, etc.). En général, il est préférable de choisir une
dénomination qui fait référence au type de manipulation elle-même : Groupe 10mg, Groupe Placebo,
Groupe Adolescents, Groupe Adultes, etc.
Effets d'ordre, et effets de rangs dans les mesures répétées
Pour contrôler les effets d'ordre, on doit faire varier l'ordre de passation des conditions expérimentales. Il
existe trois techniques, fondées sur des permutations d'ordre : le contrebalancement, qui permet de varier
l'ordre de deux conditions (ab vs ba), la permutation, qui permet de varier systématiquement l'ordre de k
conditions (abc, acb, bac, bca, cab, cba), la randomisation des ordres si le nombre de permutations est trop
important (pour 5 conditions, il y a 5! = 120 ordres possibles, dont il faut faire une sélection aléatoire des
ordres).
Pour aller plus loin sur les effets d'ordre et effets de rangs dans les mesures répétées
Exemple de mesures répétées SANS contrebalancement, avec 2 tâches pour lesquelles on mesure le nombre
d'erreurs commises :
Tâche A Tâche B
s1 1 2
s2 1 2
s3 2 3
s4 2 3
Moyenne 1.5 2.5
Ici, l'effet de la tâche est confondu avec l'ordre. La moyenne est supérieure dans la seconde condition. Cela
peut être dû à l'effet de la tâche si B est plus difficile. Cela peut être dû également à l'ordre si
l'expérimentation a conduit à une lassitude ou à de la fatigue dans la seconde condition. Cela peut-être dû à
un effet de transfert de la première tâche sur la seconde, si les tâches présentent une certaine analogie. Dans
ce cas, l'ordre parasite l'effet de la tâche puisque leurs effets peuvent être confondus.
Exemple de mesures répétées AVEC contrebalancement, avec 2 tâches pour lesquelles on mesure le
nombre d'erreurs commises :
9
Ordre Tâche A Tâche B
s1 1: Tâche A-Tâche B 3 2
s2 1: Tâche A-Tâche B 3 2
s3 2: Tâche B-Tâche A 1 3
s4 2: Tâche B-Tâche A 1 3
Moyenne 2 2.5
Pour le plan S Tâche2, on relève les moyennes suivantes : 2 vs 2.5. Le contrebalancement garanti que la
différence de moyenne n'est pas due à l'ordre de passation car l'ordre est contrôlé. Cela ne signifie pas que
l'ordre n'a pas d'effet. Ayant manipulé l'ordre, on peut distinguer également un plan S<Ordre2>, qui conduit
aux moyennes respectives de 2.5 (c'est la moyenne des scores des deux premières lignes) et 2 (la moyenne
des scores des deux dernières lignes). On peut en conclure que l'Ordre 2 (Tâche B-Tâche A) a été plus
bénéfique aux sujets, car en moyenne, ils ont commis moins d'erreurs sur les tâches.
On peut distinguer également un plan S Rang2, car chacun des sujets a été confronté à une première
épreuve et une seconde. Relevons le nombre d'erreurs en fonction du rang de l'épreuve :
1ère
Tâche 2nde
Tâche
s1 3 2
s2 3 2
s3 3 1
s4 3 1
Moyenne 3 1.5
Le tableau indique que la première épreuve est plus difficile que la seconde (quelque soit la tâche). Les
erreurs diminuent donc en fonction du rang de l'épreuve. On pourrait résumer cette situation complexe en
disant que la Tâche A est globalement plus facile, principalement parce qu'elle bénéficie de l'apprentissage
préliminaire de la Tâche B dans la condition Ordre 2.
Les effets d'ordre ne se contrôlent pas systématiquement. Ils peuvent être manipulés dans le but de
connaître des effets de transferts d'apprentissage. Les effets peuvent être bénéfiques ou préjudiciables à
l'apprentissage. Dans l'exemple précédent, on a remarqué plus de transfert de B vers A que (dans le sens
inverse).
Il est possible d'obtenir un effet de rang sans effet d'ordre. Par exemple, dans le tableau suivant, la
complexité moyenne est de 2.5. Pour l'Ordre 1, on observe 2.5 erreurs en moyenne (idem pour l'ordre 2).
En revanche les rangs correspondent respectivement à 3.5 et 1.5 erreurs. On a donc une augmentation
respective moyenne de +1 et -1 dans l'apprentissage de la première tâche et de la seconde. Il y a donc un
simple effet de rang, sans effet d'ordre (sans effet de transfert d'une tâche à l'autre). Les effets se combinent
simplement (additivement) ici : à partir d'une complexité moyenne de 2.5, on retranche .5 pour la Tâche A
et on ajoute 1 lorsque A est donnée en premier. On obtient par conséquent : 2.5 - .5 + 1 = 3, comme indiqué
dans le tableau. Idem pour les autres cas.
Ordre Tâche A Tâche B
s1 1: Tâche A-Tâche B 3 2
s2 1: Tâche A-Tâche B 3 2
s3 2: Tâche B-Tâche A 1 4
10
s4 2: Tâche B-Tâche A 1 4
Moyenne 2.5 2 3
Par des effets complexes de combinaisons des facteurs, il est également possible d'obtenir également un
effet d'ordre sans effet de rang. Par exemple, dans le tableau suivant, la complexité moyenne est de 2.5.
Dans l'Ordre 1, on observe 2 erreurs en moyenne, contre 3 dans l'ordre 2. A chaque rang, en revanche, le
nombre moyen d'erreurs est 2.5. L'Ordre 2 est ici préjudiciable à l'apprentissage des deux tâches, car
l'apprentissage de B est difficile en premier et produit un effet négatif sur l'apprentissage de A.
Ordre Tâche A Tâche B
s1 1: Tâche A-Tâche B 1 3
s2 1: Tâche A-Tâche B 1 3
s3 2: Tâche B-Tâche A 2 4
s4 2: Tâche B-Tâche A 2 4
Moyenne 2.5 1.5 3.5
11
Chap 2. Construction de conditions expérimentales par tirage au sort ou permutations
Séries aléatoires contrebalancées de 0 et de 1
Utilisez le programme chap2.m afin de découvrir comment tirer au sort des conditions expérimentales par
tirage au sort ou permutation. Un premier exemple consiste à choisir aléatoirement une série de zéros et de
uns dans le but par exemple d'assigner aléatoirement des sujets à un groupe expérimental ou à un groupe
contrôle, en fonction de l'ordre alphabétique. On ne souhaite par exemple surtout pas assigner les 10
premiers noms de l'alphabet à la condition expérimentale et les 10 derniers à la condition contrôle, car cela
comporterait un biais de sélection en fonction du nom.
Code %% Générer une série de 0 et 1 aléatoirement
clc %efface l'écran
clear all %efface les variables existantes
randi([0 1],10,1) %Choisir dans l'ensemble (0,1), une série de 10, une
fois.
% randi([0 2],10,2) ... Choisir dans l'ensemble (0,1,2), une série de
10, deux fois.
Output
ans =
1
1
0
1
1
0
0
1
1
1
>>
La solution générée ci-dessus pose néanmoins problème car le nombre de 0 et de 1 n'est pas équilibré (6
versus 4 au lieu de 5 versus 5), alors que nous souhaitons autant de participants dans les deux groupes. La
solution est indiquée ci-dessous :
Code conditions=[zeros(10,1);ones(10,1)]' % on crée une suite équilibrée de
zéros et de uns. Dix de chaque.
newpositions=randperm(20) %On crée une seconde liste d'indices de
position allant de 1 à 20. Aléatoire.
scrambledConditions= conditions(newpositions) %La dernière phase
consiste à tirer les uns et les zéros de la première liste en fonction
des positions donnée par la seconde liste.
Output
conditions =
Columns 1 through 13
0 0 0 0 0 0 0 0 0 0 1 1 1
12
Columns 14 through 20
1 1 1 1 1 1 1
newpositions =
Columns 1 through 13
10 3 9 19 15 7 17 8 18 20 4 11 1
Columns 14 through 20
14 2 16 12 6 13 5
scrambledConditions =
Columns 1 through 13
0 0 0 1 1 0 1 0 1 1 0 1 0
Columns 14 through 20
1 0 1 1 0 1 0
>>
La solution obtenue est satisfaisante car la variable scrambledConditions contient des 0 et des 1 en nombre
équivalent. Il a suffit de commencer par générer une première liste de 10 zéros et de 10 uns, sans ordre
aléatoire. La seconde variable nommée newpositions tire aléatoirement une liste de 20 positions (par
exemple, 10e, 3e, 9e, etc.). Enfin, les vingt 0 et 1 de la première liste sont tirés en fonction des positions
mémorisées dans la seconde liste. Par exemple, on choisit le 10e élément de la première liste, qui devient le
premier élément de la nouvelle liste appelée scrambledConditions. On prend ensuite le 3e élément, qui
devient le second, etc. Les 10e et 3e éléments étant des zéros, cela explique que scrambledConditions
commence par deux zéros.
Séries aléatoires d'essais expérimentaux
Si l’on souhaite montrer par exemple une centaine de photographies dans un ordre aléatoire à des sujets, la
fonction randi pose toujours le problème qu'elle est fondée sur un tirage aléatoire avec remise. Dans
l'exemple ci-dessous, le 46 a été tiré deux fois, ce qui n'est pas souhaitable.
Code x=randi(50,50,1)'
%draw 100 numbers between 1 and 100 with replacement
Output
x =
Columns 1 through 13
17 11 26 46 32 6 20 3 26 22 50 41 25
Columns 14 through 26
45 7 20 47 46 36 31 18 47 7 37 33 42
13
Columns 27 through 39
20 38 42 17 28 49 28 17 31 19 38 21 25
Columns 40 through 50
35 49 17 42 37 48 2 18 34 15 12
>>
La solution consiste à utiliser de nouveau randperm. Dans l'exemple ci-dessous, aucun doublon n'a été
généré. Pour s'en assurer, on vérifie que mean(sort(x)==[1:50]) est bien égal à 1.
Code x=randperm(50)
mean(sort(x)==[1:50])
Output
x =
Columns 1 through 13
34 25 5 35 48 46 40 13 15 44 27 38 8
Columns 14 through 26
42 41 11 43 45 6 22 31 17 50 39 23 7
Columns 27 through 39
20 19 29 16 3 32 2 37 4 28 30 1 9
Columns 40 through 50
12 18 33 14 10 21 47 49 24 26 36
ans =
1
>>
Contrebalancement de conditions expérimentales
Dans le cas où l’on souhaite tester cinq conditions expérimentales, l'expérimentateur doit s'assurer que les
conditions soient contrebalancées afin de ne pas produire d'effets d'ordre. Voici le programme générant les
5! = 120 permutations de 5 conditions :
Code clc
clear x
x= perms([1:5])
%verif :
length(x)==factorial(5)
14
Output
x =
5 4 3 2 1
5 4 3 1 2
5 4 2 3 1
5 4 2 1 3
5 4 1 2 3
5 4 1 3 2
5 3 4 2 1
5 3 4 1 2
5 3 2 4 1
5 3 2 1 4
5 3 1 2 4
5 3 1 4 2
5 2 3 4 1
5 2 3 1 4
5 2 4 3 1
5 2 4 1 3
5 2 1 4 3
5 2 1 3 4
5 1 3 2 4
5 1 3 4 2
5 1 2 3 4
5 1 2 4 3
5 1 4 2 3
5 1 4 3 2
4 5 3 2 1
etc.
jusqu'à la 120e ligne :
1 5 4 3 2
ans =
1
>>
La solution ci-dessus ne serait pas envisageable si, par exemple, nous avions 10 conditions expérimentales
au départ, puisqu'il existe plus de 3 millions de possibilités d'ordre avec 10 conditions. Le programme
suivant attribue à chacun des 30 participants un ordre tiré au hasard.
Code
Output ans =
3628800
expConditionsByParticipant =
9 4 1 3 6 2 10 8 5 7
15
4 6 7 10 3 2 1 5 9 8
10 1 6 8 5 2 7 9 4 3
9 3 5 6 4 7 1 8 10 2
4 9 2 3 1 10 8 7 6 5
2 1 8 3 7 9 6 5 4 10
8 5 9 10 7 6 2 4 3 1
5 4 7 10 2 6 1 3 9 8
1 5 6 7 10 2 8 9 3 4
5 4 10 7 2 3 8 1 9 6
9 6 1 5 2 8 4 7 10 3
3 9 1 6 7 10 8 4 2 5
2 9 7 6 1 8 3 5 10 4
4 3 10 5 2 1 8 9 6 7
8 5 6 3 7 10 1 9 2 4
9 8 10 5 6 1 7 4 2 3
10 9 5 4 1 8 3 6 7 2
4 8 6 10 9 5 2 7 1 3
5 9 8 3 4 10 7 6 2 1
3 4 9 7 6 10 2 8 5 1
6 10 9 3 8 7 4 1 2 5
3 5 8 10 9 1 4 7 6 2
9 3 6 2 7 4 8 1 5 10
3 10 4 5 2 9 1 7 8 6
3 4 2 10 6 5 7 1 9 8
3 2 4 9 6 8 10 5 7 1
2 4 9 6 10 7 5 8 1 3
7 2 1 3 6 9 5 10 4 8
9 2 8 5 10 1 4 6 3 7
9 10 8 3 7 6 2 4 1 5
1 3 6 7 10 8 2 5 9 4
7 2 10 9 3 1 8 4 6 5
1 4 3 5 6 9 10 7 8 2
8 9 7 10 5 1 2 4 6 3
3 5 6 2 1 4 10 7 8 9
9 7 4 5 10 6 3 2 8 1
7 8 2 10 3 4 1 5 9 6
5 7 6 1 4 2 9 10 3 8
5 2 8 3 4 6 7 1 10 9
1 3 6 2 7 10 5 4 9 8
8 5 10 1 6 2 4 3 7 9
8 9 5 10 3 2 4 7 1 6
1 7 9 2 10 5 4 3 6 8
3 10 1 9 8 2 4 5 6 7
4 7 10 1 6 2 9 5 3 8
9 8 3 5 6 10 2 7 4 1
3 5 10 9 6 8 2 4 7 1
3 8 1 5 2 6 7 4 9 10
7 5 3 9 8 6 1 10 4 2
2 1 6 10 8 7 9 3 4 5
>>
Sélections et contrebalancement de conditions expérimentales
Imaginons une expérimentation visant à manipuler un facteur à sept modalités, et que l’on ne souhaite pas
administrer plus de trois conditions expérimentales par participant, afin d'éviter des effets de fatigue. Il faut
donc 1) sélectionner tous les triplets possibles (e.g., abc) et 2) générer toutes les permutations possibles par
16
triplet (e.g., abc, acb, bac, bca, cab, et cba). Au final, on réalise qu'un échantillon de 60 participants serait
parfait pour satisfaire l'équilibre trouvé.
Code
clc
nConditions =nchoosek(5,3)
conditions=nchoosek([1:5],3)
Output
nConditions =
10
conditions =
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
>>
Avec les permutations :
Code
clc
clear all
n=5;
k=3;
nConditions =nchoosek(n,k);
conditions=nchoosek([1:n],k);
expConditions=[];
for ligne=1:nConditions
expConditions=[expConditions;perms(conditions(ligne,:))];
end
expConditions
Output
expConditions =
3 2 1
3 1 2
2 3 1
2 1 3
17
1 2 3
1 3 2
4 2 1
4 1 2
2 4 1
2 1 4
1 2 4
1 4 2
jusqu'à ...
5 4 3
5 3 4
4 5 3
4 3 5
3 4 5
3 5 4
(soit, 60 possibilités)
>>
18
Chap 3. Création informatisée de stimuli
Alternative aux logiciels de dessin
Pour créer un ensemble de stimuli de même nature (par exemple, 10 lignes horizontales de 5 à 10
centimètres), le réflexe est d'ouvrir un logiciel de dessin de type photoshop/gimp/inkscape pour créer les
stimuli et les enregistrer dans 10 fichiers séparés. Procéder de même pour fabriquer 100 stimuli est non
seulement une solution laborieuse, répétitive et coûteuse en temps, mais de surcroît une source d'erreurs de
manipulation. MATLAB permet de créer très simplement des images, car on considère qu'une image est
une matrice de nombres correspondant au codage des couleurs de chacun des pixels. Le manuel de
Rosenbaum (2007) illustre bien cette capacité de MATLAB. Nous développons ici quelques exemples
simples qui illustrent les bénéfices de la programmation dans ce domaine.
Dix stimuli de taille croissante avec linspace
Pour créer 10 stimuli croissants en taille (par exemple, 10 lignes horizontales de 5 à 10 centimètres), la
fonction linspace vous permet de calculer les intervalles automatiquement. Le premier code indique qu'on
souhaite trois nombres espacés régulièrement de 5 à 10, et le code qui suit indique qu'on souhaite 10
nombres espacés régulièrement de 5 à 10.
>> linspace(5,10,3)
ans =
5.0000 7.5000 10.0000
>> linspace(5,10,10)
ans =
Columns 1 through 9
5.0000 5.5556 6.1111 6.6667 7.2222 7.7778 8.3333 8.8889 9.4444
Column 10
10.0000
>>
L'étape qui suit consiste à créer des formes et les remplir d'une couleur. La fonction fill remplit pleinement
cet objectif. Puisqu'on souhaite ici une simple ligne d'une épaisseur visible, on doit construire des
rectangles. La fonction fill permet de tracer comme si nous tenions un feutre sans le lever un polygone.
Nous souhaitons commencer par le coin sud ouest (x = 0 et y = 0), nous déplacer vers le coin sud est (x = 5
et y = 0), monter vers le nord est (x = 5 et y = .1), et revenir vers le nord ouest (x = 0 et y = .1). Par défaut,
fill boucle la boucle en revenant vers le sud ouest. Les valeurs que nous venons de décrire sont indiquées
dans le programme suivant par les variables x = [0 5 5 0 ] et y = [0 0 .1 .1]. La dernière
option 'g' indique qu'on souhaite un remplissage en vert. La fonction axis permet de voir les
coordonnées du rectangle dans un environnement plus large.
Code %% Generate one rectangle x=[0 5 5 0 ] y=[0 0 .1 .1] fill(x,y,'g') axis([0 10 -1 1])
19
Output
Dans le programme suivant, on génère 10 rectangles de taille croissante, qu'on décale d'une valeur de -.2
sur l'axe des y. Par défaut, les 10 rectangles sont générés sur des figures différentes mais en utilisant la
fonction hold on, tous les rectangles se dessinent sur une même figure.
Code
%% Generate N rectangle images of increasing size and place
them on a single figure
%Parameters
Nrectangles = 10
startLength =1
endLength =10
%Sizes
lengthLine=linspace(startLength,endLength,Nrectangles)
%Build rectangles and shift the position forward
y=[0 0 .1 .1 ]
shift =-.2
hold on
for lengthNum=1:Nrectangles
x=[0 lengthLine(lengthNum) lengthLine(lengthNum) 0 ]
y=y+ shift
fill(x,y,'g')
end
axis off
Output
20
Si on souhaite créer 10 figures différentes pour chacun des rectangles, il faut commenter la commande
hold on dans le programme précédent et attribuer un numéro de figure à chaque passage dans la
boucle (figure(lengthNum)).
Code % hold on
for lengthNum=1:Nrectangles
figure(lengthNum)
x=[0 lengthLine(lengthNum) lengthLine(lengthNum) 0 ]
y=y+ shift
fill(x,y,'g')
axis([0 10 -2 2])
axis on
end
Soixante stimuli de couleurs et de formes différentes à partir de huit stimuli noirs
Supposons que pour un test vous ayez besoin de créer un ensemble de stimuli dont les caractéristiques de
formes et de couleurs doivent varier. Vous souhaitez par exemple dans ce test présenter des figures
(triangles, carrés, ronds, etc.) et pour chacune de ces figures, disposer de différentes couleurs possibles
(triangle bleu, triangle vert, etc.). Une fois que vous avez créé les différentes formes de figures dont vous
avez besoin (à partir d’un logiciel graphique classique), vous devez générer les différentes variations de
couleur pour chacune des figures, ce qui manuellement prend un temps conséquent. Avec ce programme,
les variations de couleur sont appliquées automatiquement. Vous pouvez aussi choisir d’attribuer
automatiquement aux figures crées un nom qui en refléterait la forme et la couleur. Cette méthode apporte
un gain de temps considérable et des modifications possibles à l’infini. Ainsi, pour modifier une (ou
plusieurs) couleur(s) (ou forme), vous n’aurez pas à recréer chacune des figures, il suffira de relancer le
programme en modifiant simplement les codes couleurs dans le programme.
Une image couleur est généralement décomposée en matrices de trois niveaux, codant chacun pour les trois
niveaux de couleur : rouge, vert et bleu (RGB), chaque couleur est ainsi précisément définie par un vecteur
de trois valeurs selon un standard donné, par exemple, dans le système décimal, rouge est codé par [255 0
0], noir par [0 0 0], et bleu par [0 0 255].
Les figures originales de notre exemple sont toutes de couleur noire avec un fond transparent. Ces fichiers
de type png doivent dans une première étape être chargés. Ensuite, si ce n’a pas été initialement fait,
transformer la couleur du fond en gris (fonction BackgroundColor). Puis par une technique de
vectorisation, modifier le noir selon les couleurs désirées. Ensuite, le programme enregistre et nomme
chacune des images ainsi créées (fonction imwrite) de manière à ce que le nom renseigne sur la forme et la
couleur de l’image, par exemple 34.jpg correspond à la forme 3 et la couleur 4. Enfin, pour insérer une
belle présentation de vos stimuli dans la description de l’expérience, vous pouvez assembler toutes les
figures générées de sorte à toutes les visualiser sur une même image.
21
Code
%% Ce programme permet de modifier automatiquement la
couleur de 8 stimuli préalablement réalisés en couleur noir
avec un logiciel de dessin. Au final, le programme génère
64 images stimuli en .jpg, avec 8 couleurs différentes par
forme.
%clear
clc
clear
%CONSTANTES %Une couleur par ligne %noir, bleu, vert,
rouge, cyan, violet, jaune, blanc.
colors=[
0 0 0
0 0 255
0 255 0
255 0 0
0 255 255
255 0 255
255 255 0
255 255 255]; %RGB colors
%Charge les images png
filenames = dir('*.png' ) %# liste les fichiers *.png
filenames = {filenames.name}'
BACKGROUNDCOLOR=[.5 .5 .5] %Vecteur pour la couleur grise
Nshapes=size(filenames,1);
for pic=1: Nshapes
picCell{pic}=
imread(char(filenames(pic)),'BackgroundColor',BACKGROUNDCOL
OR);
end
%Trouve ce qui n'est pas gris
incr=0;
figNum=0;
for shapeNum=1:Nshapes
for colorNum=1:size(colors,1)
incr=incr+1
newPic{incr}=ones(size(picCell{shapeNum}))*128
for colorDim=1:3 %change les couleurs RGB
positionNONGREYpixels=find(picCell{shapeNum}(:,:,colorDim)~
=128);
tmp=newPic{incr}(:,:,colorDim);
22
tmp(positionNONGREYpixels)=colors(colorNum,colorDim);
newPic{incr}(:,:,colorDim)=tmp;
end
newStimulus=uint8(newPic{incr});%Le nouveau
stimulus est prêt à être sauvegardé
figNum=shapeNum*10+colorNum;%On donne au stimulus
un nouveau nom
imwrite(newStimulus, sprintf('%d.jpg',figNum));%Le
stimulus est sauvegardé au format jpg
end
end
%% On souhaite une figure récapitulative mettant les 64
figures côte à côte.
incr=0;
for shapeNum=1:Nshapes
for colorNum=1:size(colors,1)
incr=incr+1;
figName= [num2str(shapeNum*10+colorNum),'.jpg']
x=imread(figName);
subplot(8,8,incr);
image(x)
axis off
end
end
Ouput 1 (capture d'écran du contenu du dossier dans lequel nous avons sauvegardé les images, avec les
icônes correspondantes)
Output 2
La figure générée par la dernière partie du programme avec subplot(8,8,...) est :
23
Chapitre 4. Expérimenter avec la Psychophysics toolbox et E-Prime
E-Prime est un logiciel de conception d’expériences très couramment utilisé en psychologie.
Avec une interface graphique à la fois simple et agréable, il permet de créer en quelques clics
des expériences aussi bien basiques que complexes. Toutefois, même si sa prise en main peut
se révéler longue et délicate, de nombreux guides et tutoriels sont disponibles sur le net1, sur
le site même du fournisseur de E-Prime, Psychology Software Tools (PST) mais également
sur leur chaîne Youtube (http://www.youtube.com/user/PSTNET). De plus, lors de
l’installation d’E-Prime sur votre ordinateur, de nombreux exemples de programmes
s’installent par défaut dans le dossier My Experiments. Il faut cependant noter qu’à l’heure
actuelle, PST n’est pas favorable à l’utilisation d’E-Prime sous Windows 8. Le fournisseur
déconseille d’effectuer le recueil de données sous ce système d’exploitation. Même s’il est
possible de créer les expériences avec Windows 8, il est vivement recommandé d’effectuer
leur exécution sous Windows 7/Vista ou XP.
Un des nombreux avantages de ce logiciel est sa compatibilité avec d’autres logiciels et
instruments de mesures physiologiques (électrocardiographie, électromyographie, réponse
électrodermale, etc.). Il est également possible de se procurer des extensions E-Prime pour
l’utiliser en IRM fonctionnelle ou avec Tobii (oculométrie). Pour se procurer le logiciel E-
Prime, il faut commander une licence auprès du fournisseur qui vous fournira une clé dongle
(comportant la licence) et le logiciel. Le logiciel est par ailleurs directement disponible en
téléchargement sur le site web de PST. La clé est nécessaire lorsque vous souhaitez créer ou
modifier un programme, le logiciel est suffisant lorsque vous souhaitez l’exécuter.
Le logiciel E-Prime est constitué de plusieurs composantes ayant chacune leur importance : E-
Studio est le programme qui vous permet de créer votre expérience, E-DataAid est un simple
tableur permettant d’afficher et de traiter (dans une faible mesure) les données des participants
(un fichier .edat2 est automatiquement créé à la fin de chaque passation) et qui vous permet de
les exporter dans des logiciels statistiques (SPPS, Statview) ou dans d’autres tableurs (Excel),
E-Merge permet de fusionner dans un même tableau les données de l’ensemble de vos
participants, E-Run permet de lancer directement l’expérience sans passer par E-Studio (un
fichier .ebs2 est automatique crée lorsque vous enregistrez votre expérience), enfin, E-
Recovery vous permet de récupérer les données d’un participant même si celui-ci n’a pas
terminé l’expérience.
Ce chapitre vise essentiellement à présenter succinctement les différentes composantes du
logiciel E-Prime ainsi qu’à donner quelques astuces et conseils de base pour faciliter sa prise
en main.
E-Studio
E-Studio est le programme qui vous permet de créer de A à Z votre expérience. Lorsque que
vous démarrez le logiciel pour débuter une nouvelle expérience, plusieurs options s’offrent à
vous :
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"! #$%&! '$%&! ($)&*+,,$)&! -$%.! ($//*)(*.! ,0*1(*,,*)2! 3!4%+5*! 5*! 6%.'+*!7! 8(.+2! -9.! :$/+)+(! ;<9.=$))*9%! *2!
-.$-$&8! -9.! ,9! >9+&$)! 5*&! 6(+*)(*&! 5*! ,0?$//*! *2! 5*! ,9! 6$(+828! 5*! ,0@)+'*.&+28! 5*! A$+2+*.&!B!
<22-BCCDDDE/&<&E%)+'F-$+2+*.&EG.C.*&&$%.(*&C*F-.+/*CH%+5*E-5G!
Ces options se présentent sous forme de Templates, c'est-à-dire de modèles de conception
préprogrammés. Tandis que les Templates de type « Basic » présentent déjà un début de
structure à votre future expérience, les Templates de type « Blank » sont complètement
vierges. Même s’il est conseillé de commencer par un Template Blank, vous pouvez
commencer par un Basic afin d’essayer d’apprivoiser le logiciel sans avoir à partir de zéro.
Vous pouvez également charger les exemples fournis par le logiciel et situés dans le dossier
My Experiments afin d’avoir des exemples concrets et se rapprochant de ce que vous
souhaitez faire.
Votre interface graphique est constituée de plusieurs parties : la partie « Toolbox » contient les
différents objets nécessaires à la conception de votre expérience, la partie « Structure »
permet d’avoir une vue d’ensemble de l’expérience, la partie « Properties » affiche les
propriétés de l’objet activé, et enfin, la fenêtre principale est votre fenêtre de travail dans
laquelle vous pouvez modifier vos objets. Il est important de noter que lors de l’exécution du
programme, E-Prime effectue séquentiellement la hiérarchie donnée dans la partie structure.
Le logiciel va donc exécuter les objets de la structure les uns après les autres (il revient en
arrière dans les boucles lorsque des événements doivent être exécutés plusieurs fois). L’icône
permet de lancer l’expérience. Que ce soit pour le Template « Basic » ou « Blank », il faut
en premier lieu double-cliquer dans la partie structure sur la procédure « SessionProc » qui va
ainsi s’ouvrir dans votre fenêtre de travail. Pour insérer des objets, il suffit simplement de
cliquer sur l’objet souhaité et de le glisser sur votre procédure. Double-cliquez ensuite sur ce
dernier pour le configurer. L’icône (en haut à gauche) permet de définir l’ensemble des
propriétés de chaque objet.
Propriétés générales de l’expérience
Pour accéder à ces propriétés, il est nécessaire de double-cliquer, dans la partie structure, sur
l’objet appelé « Experiment Object ». Il est alors possible de paramétrer différentes modalités
de votre expérience. Par exemple, l’onglet « General » vous permet de résumer votre
expérience et d’indiquer le nom des auteurs. L’onglet « Startup Info » vous permet de
configurer les informations que vous souhaitez demander à vos participants (âge, sexe, date de
naissance, main dominante) mais également d’indiquer dans quel groupe appartient votre
sujet. Des fenêtres s’ouvriront au lancement de l’expérience et permettront ainsi de rentrer
toutes ces informations. Il est bien évidemment possible de créer et demander autant
d’informations que nécessaire. Autre exemple, l’onglet « Devices » est important parce qu’il
vous permet d’ajouter différents appareils, dispositifs nécessaires à votre expérience (souris,
clavier, boutons réponses, joystick, etc.). Il vous permet également de relier vos dispositifs
entre eux lorsque vous combiner par exemple votre expérience à des mesures physiologiques
(ports parallèles, ports sériels, etc.).
Toolbox
Plusieurs types d’objets sont disponibles dans la Toolbox. Voici une brève présentation des
outils les plus importants.
- List : cet objet est fondamental car c’est lui qui va vous permettre de définir les
différentes conditions (procédures) de votre expérience, les différents blocks, le
nombre de stimuli, l’ordre d’apparition des stimuli et des procédures.
Comme vous pouvez le voir dans l’image ci-dessous, trois colonnes sont déjà
prédéfinies. La première, Weight, concerne le nombre de fois que votre ligne sera lue.
Dans cet exemple, nous avons deux procédures (conditions), « controle » et
« indices » qui seront effectuées chacune une fois. Le nom des procédures correspond
à vos tâches ou vos conditions et elles seront créées automatiquement (et visibles dans
la partie structure de votre fenêtre E-Prime). Dans les propriétés de votre liste, vous
pouvez définir dans quel ordre vous souhaitez que ces procédures soient effectuées :
aléatoire, contrebalancé, séquentiel, etc.
La colonne « Nested » est importante puisqu’elle vous permet de créer des sous listes.
Le plus simple pour expliquer son rôle est de donner un exemple. Imaginons une
simple tâche de mathématiques dans laquelle les participants doivent alterner à chaque
essai entre des additions et des soustractions. Pour une même liste de nombres, ils
doivent par exemple ajouter 3 ou soustraire 3 sans qu’aucun de ces nombres
n’apparaisse deux fois dans un même bloc. L’ajout d’une même sous-liste appelée
« nbre » dans notre exemple ci-dessous à gauche pour nos deux conditions d’addition
et de soustraction permet ainsi de placer dans cette sous-liste la liste des stimuli (les
nombres, « Nb ») en indiquant les résultats pour les deux conditions (visibles dans les
colonnes « Addition » et « Soustraction » dans l’image suivante à droite. De cette
façon, pour deux procédures différentes « Add » et « Sous », nous faisons appel à une
même liste de stimuli qui apparaissent chacun une seule fois et qui peuvent aussi bien
être attribués à la condition Addition qu’à la condition Soustraction.
- ImageDisplay : cet objet permet l’affichage d’une image. Pour choisir l’image
souhaitée, cliquez sur l’icône de propriétés de votre objet. Une nouvelle fenêtre
s’ouvre dans laquelle plusieurs onglets permettent la modification de différents
paramètres. L’onglet général permet ainsi de charger l’image désirée en la
sélectionnant dans votre dossier. Attention, il est conseillé de placer vos images dans
le même dossier que celui où se trouve votre expérience. Si votre expérience consiste
par exemple à mémoriser plusieurs séries d’images, au lieu de charger une seule
image, vous pouvez faire appel à une liste de stimuli que vous aurez auparavant placés
dans une liste. Pour ce faire, vous devez faire appel à la colonne de votre liste
contenant les stimuli en indiquant le nom de la colonne entre crochet,
[NomColonneStimuli], dans le Filename.
L’onglet « Duration/Input » est essentiel puisqu’il vous permet entre autres de
paramétrer la durée d’apparition des stimuli, les touches réponses s’il y en a, mais
également d’indiquer si la réponse donnée est correcte ou non. Dans l’exemple ci-
dessous, on peut voir que la durée du stimulus est infinie, c'est-à-dire que E-Prime ne
passera à l’évènement suivant que lorsque le participant aura donné une réponse. Mais
vous pouvez également choisir une durée de votre choix si vous souhaitez que votre
image apparaisse uniquement pendant un temps déterminé. Le clavier a été ajouté dans
la partie Device(s) puisque c’est avec lui que les participants donneront leurs réponses.
En ce qui concerne les options de réponses, les touches réponses possibles sont
« 012456789 » dans le cas de notre tâche de mathématiques, et les réponses correctes,
que vous aurez précédemment indiquées dans une colonne de votre liste de stimuli, est
à placer dans la partie « Correct: » entre crochets (ici, [Addition]). Ainsi, dans votre
tableau de données obtenu à la fin de l’expérience, une colonne vous indiquera par un
1 ou un 0 si la réponse donnée était correcte ou non.
Une autre partie des propriétés qui est importante est l’onglet « Logging » dans lequel
vous pouvez sélectionner toutes les informations que vous souhaitez obtenir dans votre
tableau de données final. Vous pouvez par exemple choisir d’obtenir le temps passé
sur l’image (response time, RT), la justesse des réponses (accuracy, ACC), le moment
auquel l’image est apparue (important lorsque vous synchronisez E-Prime à un
appareil d’enregistrement physiologique), etc.
- Slide : le principe de la slide est le même que celui de l’image. Une slide vous permet
de placer sur une même « image » plusieurs éléments qui s’afficheront en même temps
à l’écran. Vous pouvez aussi bien placer plusieurs images ensemble qu’une image et
un son ou un son et une vidéo. Pour modifier les propriétés de la slide, vous devez
cliquer sur l’icône , et pour modifier les propriétés de vos objets à l’intérieur de la
slide, vous devez cliquer sur l’icône après avoir sélectionné l’objet souhaité.
- Feedback : vous pouvez choisir de donner un feedback après chacune des réponses de
vos participants. De cette façon, un message peut par exemple les informer sur la
justesse des réponses, le temps de réponse ou encore le pourcentage de bonnes
réponses. Sur l’image suivante, vous pouvez voir la configuration basique du feedback
qui informe les participants d’une réponse correcte (dans la partie basse de l’objet
feedback se trouvent les onglets pour les réponses correctes, les réponses fausses,
l’absence de réponse et l’attente), ainsi que le temps de réponse et le pourcentage de
réponses correctes.
- MovieDisplay, SoundIn, SoundOut : ces trois objets vous permettent, de la même
façon que pour les images, d’ajouter des vidéos, des sons ou encore d’enregistrer des
sons si vous disposez un micro (à configurer).
- Inline : cet objet est important puisqu’il va vous permettre d’ajouter des lignes de
codes (en Visual Basic) pour réaliser des commandes plus complexes que celles
proposées par E-Prime. Par exemple, le code suivant permet de rendre visible le
curseur de la souris :
'Show Mouse
Mouse.ShowCursor true
Le code suivant permet d’envoyer un signal à l’aide d’un trigger (un signal
déclencheur) à un appareil d’enregistrement physiologique afin de commencer
l’enregistrement (et permettant ainsi de synchroniser l’ensemble).
Dim strData As String
strData = "%"
'(E-Studio generates the following script when the serial device is
'added to the experiment: Dim Serial As SerialDevice).
Serial.WriteString strData
tps=clock.read
- Label : l’outil Label est utilisé pour marquer une position dans une procédure de votre
expérience. Le label est utile lorsque l’on souhaite accéder directement à un point. Sa
seule propriété est la position qu’il occupe dans votre procédure.
- Wait : cet objet vous permet simplement d’ajouter un temps de pause entre deux
événements, temps dont vous pouvez définir la durée dans les propriétés de l’objet.
- PackageCall : à l’aide de cet objet, vous pouvez synchroniser d’autres appareils à E-
Prime (appareils d’enregistrement physiologique par exemple). Attention, des
extensions sont parfois nécessaires selon le type d’appareil que vous utilisez.
E-Merge
Comme nous l’avons expliqué en introduction, E-Merge permet de compiler plusieurs fichiers
.edat2 ensemble (fichiers comportant les données de chaque participant) afin d’obtenir un seul
et même fichier. Ce programme permet donc un gain de temps considérable ainsi qu’une
importante économie de copier-coller lorsque le nombre de sujets est élevé.
Pour compiler l’ensemble des données vous devez sélectionner les fichiers .edat2 que vous
souhaitez joindre et cliquer sur l’icône Merge en haut à gauche. Conservez l’option
sélectionnée par défaut (Standard Merge) et indiquez le nom que vous voulez donner à votre
nouveau fichier .emrg2.
Nous conseillons de rajouter un 0 devant le numéro de sujet des 9 premiers participants (01,
02, 03, etc.) afin que les sujets soient correctement classé par ordre de passation dans votre
fichier .edat2. Sans le 0, le sujet numéro 2 sera par exemple classé entre le 19 et le 20, le sujet
3 entre le 29 et le 30, etc.
E-DataAid
Lorsqu’un participant termine une expérience, un fichier .edat2 comportant toutes ses données
est automatiquement créé. Ce logiciel basique de traitement de données (du même type
qu’Excel) vous permet d’exporter directement les données dans un format standard et de les
ouvrir avec des logiciels d’analyses statistiques (SPSS, Statview) ou Excel. Il vous est
possible de supprimer les colonnes indésirables (elles sont nombreuses) et de les organiser
dans l’ordre souhaité à l’aide de l’option Arrange Columns . Cette option est appréciable
car même pour une simple expérience, la quantité de données enregistrées est considérable ce
qui rend malheureusement les résultats peu lisibles si on ne les réorganise par correctement.
Sans passer par cette option, vous pouvez simplement utiliser le clic droit de la souris sur le
nom d’une colonne pour la masquer (option Hide) Même s’il est possible d’utiliser des filtres
avec l’option Filter ou d’effectuer des analyses basiques avec l’option Analyse, nous
conseillons vivement d’exporter vos données vers des logiciels spécialisés.
E-Recovery
Ce programme peut vous « sauver la vie » plus d’une fois. Nous le savons tous, lors d’une
passation d’expérience, nous ne sommes jamais à l’abri d’un bug informatique, d’une panne
de courant ou encore d’un participant qui souhaite arrêter l’expérience. Pendant l’expérience,
le logiciel E-Prime enregistre à chaque essai les données dans un fichier texte (placé dans le
dossier de votre expérience) qu’il ne convertira en fichier .edat2 qu’à la fin de l’expérience…
mais encore faut-il parvenir jusque là. C’est ici qu’intervient le programme E-Recovery qui
est capable de lire le fichier texte et de le convertir en fichier .edat2. Si une panne de courant
survient dans les derniers essais de votre expérience, il serait dommage de se passer de ces
données.
E-Run
La dernière composante du logiciel E-Prime est le programme E-Run qui va vous permettre
de démarrer directement une expérience, sans passer par le programme de création E-Studio.
De plus, la clé licence (clé dongle) n’est pas obligatoire pour lancer le programme, ce qui peut
vous permettre de faire passer plusieurs expériences en même temps (si vous disposez de
plusieurs ordinateurs). En enregistrant votre expérience après sa création, un fichier .ebs2 est
automatique créé qui est l’équivalent d’un fichier exécutable, si et seulement si le logiciel E-
Prime est installé.
Astuces
Voici quelques astuces qui vous seront nécessaires dans votre utilisation d’E-Prime :
- Une fois l’expérience démarrée, il peut parfois être nécessaire de l’arrêter (surtout
pendant les phases de test lors de sa création). Pour cela, il vous suffit d’appuyer sur
les touches Ctrl+Alt+Shift.
- Nous vous conseillons de tester votre expérience au fur et à mesure, et seulement avec
quelques essais. Par exemple, si chacune de vos conditions comporte 100 essais, vous
allez vite trouvez le temps long lors des phases de test (même si vos performances
n’en seront que meilleures !). De plus, si vous rencontrez un bug dans votre
expérience ou que vous n’obtenez pas ce que vous désirez, il est plus facile de trouver
la source du problème en testant l’expérience étape par étape plutôt qu’en testant
l’expérience à la fin de sa création.
- Vous constaterez rapidement qu’il n’est pas possible de donner le même nom à deux
objets différents. Il est donc conseillé de trouver des noms très explicites pour pouvoir
vous y retrouvez plus facilement.
- E-Prime ne prend pas en compte les accents ni les espaces. De ce fait, prenez garde à
ne pas enregistrer vos images sous des noms comportant ce type de caractère, auquel
cas votre expérience ne fonctionnera pas.
- Certaines expériences peuvent posséder des structures complexes et longues (il est
vivement conseillé de faire des programmes courts pour éviter les erreurs). En utilisant
le clic droit de la souris sur l’objet « Experiment Object » de la Structure, vous avez la
possibilité à l’aide de l’option « Allow Collapsing » de permettre le regroupement des
objets d’une même procédure (en cliquant sur les + ou les -) et d’obtenir ainsi une
hiérarchisation plus claire et lisible dans la partie structure.
- Enfin, nous vous conseillons de vérifier régulièrement les différents paramètres de vos
objets car plus ils sont nombreux plus il est facile d’oublier de les modifier,
notamment en ce qui concerne les temps d’apparition ou les données que l’on souhaite
obtenir dans le tableau de résultats. Dans la même perspective, une fois votre
expérience terminée, faites le test et vérifiez que vous obtenez bien toutes les
informations nécessaires dans votre fichier de données.
Exemple de programme pour une tâche d’alternance
Dans cette tâche les participants doivent trier des objets dans deux catégories (Gauche ou
Droite) selon des règles qui leur sont imposées. La première règle de l’expérience indique aux
sujets de trier les carrés bleus à gauche et les carrés rouges à droite. La seconde règle, faisant
appel à des stimuli d’une autre forme, impose aux participants de trier les ovales rouges à
gauche et les ovales bleus à droite. Cette tâche comporte cinq blocs de test : le premier est
consacré à l’apprentissage de la première règle (avec un feedback pour indiquer aux sujets si
leur réponse est correcte ou non), le second bloc concerne l’apprentissage de la seconde règle
(avec feedback également), les blocs 3 et 4 reprennent les deux premiers blocs mais sans
feedback (blocs d’application des règles) et enfin, le bloc 5 impose aux sujets d’alterner entre
les deux règles et donc de trier l’ensemble des stimuli.
Dans votre procédure de départ, après avoir inséré deux objets textes pour présenter
l’expérience et pour la conclure (libre à vous de prévoir des zones de présentation et de
conclusion de votre expérience), il faut insérer un outil « list » entre les deux dans lequel vous
allez inscrire sur 5 lignes, les 5 blocs de l’expérience : Bloc1, Bloc2, Bloc3, Bloc4, Bloc5.
Dans les propriétés de votre liste, onglet « selection », il faut choisir un ordre séquentiel afin
que les cinq blocs soient effectués dans l’ordre. Vous constatez alors que les cinq procédures
correspondant aux cinq blocs sont automatiquement créées dans la partie « structure » de
votre tâche. N’oubliez pas de donner des noms explicites à vos différents objets pour que cela
soit le plus clair possible (pour vous et pour tout autre utilisateur du programme).
Il vous faut maintenant construire vos différents blocs. Chaque bloc débute par une consigne
et se termine par une « diapositive » de fin de bloc (avant de passer au suivant ou de terminer
l’expérience pour le dernier bloc). Comme nous vous l’avons expliqué au début de l’exemple,
les blocs 1 et 3, ainsi que 2 et 4 sont identiques, hormis la présence d’un feedback après
chaque réponse pour les deux premiers blocs. Il est donc possible d’utiliser la même slide (ou
objet texte) consigne pour les blocs 1 et 3 et pour les blocs 2 et 4. Comme vous pouvez
également le voir sur l’image suivante, la fin de chaque procédure fait appel au même objet
« FinBloc ». Pour insérer un même objet sur plusieurs procédures, il suffit simplement
l’insérer une première fois sur votre première procédure, puis ensuite de le cliquer dessus et
de le faire glisser sur les autres procédures à l’endroit désiré.
Pour nos consignes, nous avons choisi d’utiliser des slides (l’exemple est issu d’une
expérience comportant plusieurs tâches dont les images varient d’un participant à un autre).
Pour les slides des consignes 1 à 4, nous avons insérés 4 images et 2 zones de textes. Les
images à trier apparaissent à gauche dans la slide, et sont suivies par deux flèches indiquant
les catégories dans lesquelles les images doivent être catégorisées (gauche et droite). Pour la
consigne du bloc 5, nous insérons côte à côte les stimuli à trier du même côté.
Il vous reste ensuite à définir les propriétés de vos consignes : durée, comment passer à
l’événement suivant pour commencer l’expérience, etc.
Dans cette expérience, les participants étaient libres de passer autant de temps que nécessaire
sur les consignes. Nous avons donc choisi un temps « infini » et défini une touche du clavier
(la touche espace) pour pouvoir passer à la suite. Vous pouvez choisir d’obtenir le temps
passé sur les consignes dans l’onglet « Logging » si cette donnée vous intéresse.
Dans votre procédure, entre la consigne du bloc et la fin de celui-ci, il vous faut une nouvelle
fois insérer un objet « list » dans lequel vous allez indiquer les stimuli utilisés, le nombre
d’essais, l’ordre d’apparition des stimuli, les touches réponses correspondantes, etc.
Dans notre exemple, chaque stimulus de notre procédure B1 (il faut être inventif pour trouver
des noms différents à chaque fois) est présenté 10 fois. Il faut ensuite insérer deux colonnes,
une pour les stimuli et une pour les réponses. Dans la colonne « Stimuli », vous devez
indiquer le nom sous lequel vous avez enregistré vos images dans le dossier de votre
expérience (ici, CB.bmp et CR.bmp). Dans la colonne « Reponse », la touche réponse de
notre carré bleu est la touche S et celle de notre carré rouge la touche L. Libre à vous de
choisir vos touches réponses ou vos images réponses lorsque l’expérience s’effectue avec la
souris2. Vous pouvez ensuite définir dans la partie propriétés de votre liste, l’ordre dans lequel
vous souhaitez que les images apparaissent. Si vous souhaitez un ordre précis, vous avez la
possibilité de faire autant de lignes que votre bloc comporte d’essais. Vous pouvez également
choisir des essais avec remises (dans ce cas, si votre bloc comporte 20 essais, il est possible
d’avoir 20 fois le même stimulus). Dans notre cas, nous avons choisi un ordre complètement
aléatoire.
Il reste maintenant à définir le déroulement précis de notre bloc. Dans la nouvelle procédure
créée (B1), nous choisissons de mettre une croix de fixation avant l’apparition de chaque
stimulus. Pour cela, il suffit d’insérer un simple fichier texte dans lequel on inscrit une simple
croix (le signe +) que nous centrons verticalement et horizontalement dans les propriétés de
l’objet texte (n’oubliez pas définir la durée d’apparition de la croix).
Après la croix de fixation, il faut insérer dans la procédure un objet « image » dans lequel
apparaîtrons les stimuli. Dans les propriétés de l’image, au lieu de télécharger une image fixe
dans le « Filename », il vous faut simplement indiquer entre crochet le nom de la colonne
dans laquelle vous avez indiqué le nom de vos stimuli (dans notre cas : [Stimuli])
Toujours dans les propriétés, vous devez une nouvelle fois définir le temps d’apparition des
stimuli. Cette expérience s’intéressant aux temps de réponses, un temps infini a été choisi
mais il est possible d’imposer un temps maximal.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!Par exemple, si dans votre tâche les participants doivent répondre en cliquant sur des images, vous devez pour
chacune de ces images (situées dans une slide) définir leur nom dans la partie « Properties » (par exemple
« ReponseA »), nom à ne pas confondre avec le « filename » qui correspond au nom sous lequel vous avez
enregistré votre image (par exemple, « ReponseA.bmp »). Par défaut, les images seront appelées Image1,
Image2, etc. Ensuite, dans votre liste, à la place d’indiquer une touche réponse, il vous suffit de mettre le nom de
l’image correspondant à la réponse demandée.
Comme vous pouvez le voir dans la capture d’écran ci-dessus, nous avons défini les deux
touches réponses possibles (s et l), ainsi que la colonne dans laquelle se trouve les bonnes
réponses (colonne [Reponse]). Il est important une nouvelle fois de choisir dans l’onglet
« Logging » les données que vous souhaitez obtenir.
Dans le Bloc 1 de cette expérience (comme pour le Bloc 2), nous avons choisi de donner un
feedback aux participants. Ainsi, après les objets « Croix » et « Stimuli » il faut insérer un
objet « Feedback » dans lequel vous choisissez les messages et informations que vous
souhaitez transmettre. Vous pouvez les définir dans les différents onglets prévus à cet effet
dans le bas de l’objet. Dans cet exemple, un simple message, « OK » pour les réponses justes
et « FAUX » pour les réponses fausses, apparait à l’écran. Il est ensuite nécessaire de définir
la durée du feedback mais également l’objet de référence auquel est rattaché le feedback (afin
de savoir si la réponse est juste ou fausse). Pour cela, dans l’onglet « General » des propriétés
de votre feedback, vous devez donc trouver dans la partie « Input Object Name » le nom de
votre objet « Stimuli ».
Vous devez ensuite reproduire ces différentes démarches pour l’ensemble de vos blocs, en
fonction de leurs différentes propriétés. Encore une fois, nous conseillons vivement de tester
régulièrement une expérience pour corriger au fur et à mesure d’éventuelles erreurs du
programme.
1
Analyse & modélisation
Chap 5. Importer, transformer, compiler, restructurer et agréger des données.
Importer et transformer
Les logiciels statistiques standards ne permettent pas de comparer plusieurs lignes entre elles pour recoder
des données. Ils permettent simplement de transformer des données ligne par ligne, en prenant par exemple
le logarithme de chacune des cellules d'une colonne afin de créer une nouvelle variable. Comment faire en
revanche pour coder une nouvelle variable permettant de comparer différents essais d'une ligne à l'autre ?
Nous recommandons toujours d'enregistrer le maximum de mesures au moment de la programmation d'une
expérimentation. Il peut en effet s'avérer très coûteux de devoir recommencer une expérimentation qui avait
omis une mesure qui s'avère indispensable à l'administration d'une preuve. Néanmoins, tout en ayant pris
cette précaution de départ, il arrive souvent que l'on souhaite recoder des variables après coup. Par
exemple, il peut-être utile de vouloir recoder le nombre de répétitions d'une même tâche, lorsque deux
tâches alternent de façon aléatoire, ou le passage d'une tâche à une autre signalant ce qu'on appelle
communément dans notre jargon un switch.
Pour recoder des séquences, des fonctions EXCEL peuvent être utilisées. Nous verrons qu'elles rencontrent
rapidement des limites et que MATLAB doit être privilégié. Cependant, voici quelques exemples de
recodage. Le tableau suivant représente un tableau dans lequel figure des réponses à un questionnaire. Lors
de la collecte des données, à tort ou à raison, seul un "oui" a été entré dans le cas d'une réponse affirmative
à chacune des questions (la réponse "non" est donc représenté par une case vide).
Question 1 Question 2
s1 oui
s2 oui oui
s3 oui
s4 oui
Un tableau tel que le suivant s'avérerait plus pratique pour sommer le nombre de oui par question, avec une
simple fonction somme :
Question 1 Question 2
s1 1
s2 1 1
s3 1
s4 1
Cumul 2 3
Il est possible de rechercher tous les oui et de les remplacer par des 1, mais cela peut-être périlleux si l’on
ne souhaite pas utiliser l’option "Remplacer tous". Une solution consiste à retourner un 1 si la cellule n'est
pas vide. La fonction isblank le permet. Dans le tableau suivant, on applique la formule
=SUM(IF(ISBLANK(B2:B5);0;1)).
Notez que pour traduire les formules EXCEL du français en anglais, il existe des sites internet (e.g.,
http://www.cyann.net/). Nous favorisons l'écriture anglo-saxonne néanmoins car le net dispose de beaucoup
plus de sites d'aide en ligne utilisant la langue de Shakespeare.
La fonction seule isblank renvoie les valeurs suivantes pour les quatre lignes :
FALSE
FALSE
TRUE
TRUE
2
La fonction IF(FALSE;0;1) transforme les valeurs booléennes en valeurs numériques :
1
1
0
0
Enfin, la fonction sum renvoie ensuite la somme de 1 et de 0 de chaque colonne. Le point très inhabituel est
que la formule =SUM(IF(ISBLANK(B2:B5);0;1)) ne fonctionne que si vous pressez "Ctrl+shift+entrée"
(sur PC) ou "Pomme+entrée" (sur mac), car la formule isblank s'applique à un vecteur (B2:B5).
La logique habituelle est plutôt celle-ci : si l’on souhaite calculer une somme de carrés sur EXCEL, par
exemple pour les chiffres 1, 2 et 3, on calcule tout d'abord une colonne des carrés grâce à la fonction
POWER(...;2) qu'on applique à chaque ligne afin d'obtenir les chiffres 1, 4, et 9. Ce n'est qu'après cette
étape que nous calculons la somme des carrés par la fonction =SUM(B1:B3). Si l’on souhaite réaliser tous
ces calculs en une seule passe, il faut alors écrire =SUM(POWER(A1:A3;2)) et presser à nouveau
"Ctrl+shift+entrée" (sur PC) ou "Pomme+entrée" (sur mac), sans quoi un message d'erreur apparaît. Ce
type de formule est appelé "array formula".
1 1
2 4
3 9
14
Un autre exemple illustre le recodage d'une colonne mal codée. Il est en effet inopportun de coder des
valeurs de plusieurs variables au sein d'une même cellule comme c'est le cas dans la première colonne du
tableau suivant, qui indique que le premier sujet a subi les conditions x et y, que le second a subi la
condition x seulement, le troisième la condition y seulement, et le quatrième aucune condition. Dans la
seconde colonne, la formule =IF(FIND("x";A1)>=1;"x";"") ne fonctionne pas très bien car elle renvoie
un message d'erreur lorsque la fonction FIND ne trouve pas "x". Dans le cas où la fonction FIND trouve x,
elle renvoie sa position dans la chaîne de caractère de la cellule A1. Si la chaîne de caractère "yETx"
figurait dans la cellule A1, FIND("x";A1) renverrait la valeur 4 et FIND("x";A1)>=1 renverrait par
conséquent la valeur TRUE. Cette fonction ne fonctionne pas lorsqu'elle ne trouve rien. La solution
consiste à utiliser la fonction ISERROR. La formule =IF(ISERROR(FIND("x";A1));"";"x") permet
donc de renvoyer la valeur TRUE lorsque "x" n'est pas trouvé, et dans ce cas, on remplit la cellule d'un vide
""; dans le cas contraire, on remplit la cellule d'un "x". Idem, afin de repérer les y, on utilise
=IF(ISERROR(FIND("y";A1));"";"y"). Les 3e et 4e colonnes sont maintenant conformes aux attentes,
en séparant clairement la dimension X de la dimension Y.
xety x x y
x x x
y #VALUE! y
rien #VALUE!
Pour recoder des séquences, des règles simples dans EXCEL peuvent donc être utilisées (IF = ...), mais
elles deviennent ingérables quand la complexité du recodage visé augmente. Prenons l'exemple d'une
expérimentation dans laquelle un participant doit alterner/switcher entre deux tâches (1 et 2) de façon
aléatoire, par exemple de la façon suivante 11211122121 etc. On peut calculer après coup, la présence d'un
switch (i.e., le passage de 1 à 2 ou de 2 à 1) qui est susceptible d'entraîner un coût cognitif. La présence
d'un switch sera codée 1 et la répétition d'une tâche sera codée 0. En recodant de cette façon, nous obtenons
une nouvelle variable switchLines : 00110010111. Pour étudier de façon encore plus précise les
3
mécanismes cognitifs qui permettent d'alterner entre deux tâches, nous pouvons calculer le nombre de fois
que les tâches sont répétées après un switch, par exemple --001201000 (le symbole - signifie que rien n'est
recodé car aucun switch ne s'est encore produit ; 2 signifie qu'on a cumulé 2 répétitions, etc.). Cela
permettra de tester l’hypothèse que l'exécution d’une tâche est accélérée lorsqu’elle est répétée. On peut
enfin souhaiter calculer le nombre de répétitions d'une même tâche (par exemple, la tâche 1) ayant été
effectuées avant de revenir sur l'autre tâche (la tâche 2). Pour la situation 21112, ce nombre est 3 lorsqu'on
revient vers la tâche 2, puisqu'on a effectué 3 fois la tâche 1 entre les deux tâches 2. C'est en fait le nombre
de répétitions entre deux switchs. La nouvelle variable recodée (---1--3-211) permettra de tester
l’hypothèse que plus une tâche a été récemment inhibée (plus l’inhibition est récente), plus il est difficile de
l'exécuter à nouveau. L'intérêt de ce chapitre n'est pas l'exemple lui-même, mais la compréhension que dans
ces trois exemples, il est opportun de connaître l'algorithmique que l'on va traduire ici par un court
programme Matlab. Pour l'exemple, ouvrez le fichier chap5transform.m.
L'importation d'un fichier de données dans Matlab est facile, il suffit d'utiliser la fonction import dans le
menu. Dans Matlab, on commencera par importer les données 11211122122 du fichier excel chap5.xls en
ouvrant dans le menu principal "Files/Import data...". Une fois l'importation terminée, Matlab génère une
variable data qu'il est préférable de ne pas effacer, une précaution consiste alors à utiliser la commande
clearvars -except data, lorsque l’on veut tout effacer sauf cette variable. Pour rappel, il vaut
mieux effacer toutes les variables avant de commencer, sans quoi on prend le risque de réécrire sur des
variables existantes qui n'auront pas nécessairement le bon dimensionnement.
La première partie du programme est simplissime :
pour lineNum=2:length(data)
si data(lineNum)~= data(lineNum-1)
alors switchLines(lineNum)=1;
Ce qui signifie que si la ligne actuelle est différente de la ligne précédente, alors la ligne comporte un
switch. Pour la suite, nous invitons le lecteur à tenter de coder les autres variables --001201000 et ---1--3-
211 afin de comparer le code que nous proposons au sien. Nous proposons ici deux solutions, une courte
peu lisible, et une plus longue plus lisible. L'exemple illustre le cas fréquent d'un code plus court plus
élégant, mais pas nécessairement plus utile du point de vue de sa lisibilité.
Code %En premier lieu, choisir File/Import data et ouvrir chap5.xls situé
dans le dossier chap5xls
%clean up
clc
clearvars -except data
%dimensionnement
switchLines=zeros(length(data),1);
NTasksRepBeforeGoingBack=nan(length(data),1);
numTasksRepAfterSwitch=nan(length(data),1); %0 is a switch
%Trouve les switchs
switchLines(1)=0;
for lineNum=2:length(data)
if data(lineNum)~= data(lineNum-1)
switchLines(lineNum)=1;
end
end
%Trouve les 1er et 2nd switchs
4
switchPositions=find(switchLines==1);
firstSwitchLineNum=switchPositions(1);
secondSwitchLineNum=switchPositions(2);
% main (code principal) (version courte)
foundPreviousSwitch=0;
for lineNum=secondSwitchLineNum:length(data)
if switchLines(lineNum)==1
numTasksRepAfterSwitch(lineNum)=0;
lineNum2=lineNum;
while foundPreviousSwitch==0
lineNum2=lineNum2-1;
if switchLines(lineNum2)==1
foundPreviousSwitch=1;
NTasksRepBeforeGoingBack(lineNum)=lineNum-lineNum2;
numTasksRepAfterSwitch(lineNum2)=0;
if lineNum-lineNum2 >1
incr=0;
for lineBtw=lineNum2+1:lineNum-1
incr=incr+1;
numTasksRepAfterSwitch(lineBtw)=incr;
end
end
end
end
foundPreviousSwitch=0; %Remise à zéro
end
end
%Montre le résultat
switchPositions'
switchLines'
NTasksRepBeforeGoingBack'
numTasksRepAfterSwitch'
Output (Pour rappel NaN signifie Not a Number, précisant que la cellule de la matrice ne contient rien)
ans =
3 4 7 9 10 11
ans =
0 0 1 1 0 0 1 0 1 1 1
ans =
NaN NaN NaN 1 NaN NaN 3 NaN 2 1 1
ans =
NaN NaN 0 0 1 2 0 1 0 0 0
5
Le code indiqué maintenant est un peu plus long, mais nettement plus simple, plus lisible et donc moins
susceptible de provoquer des bugs. Ce code est fondé sur le comptage des tâches au fur et à mesure, plutôt
que sur le retour vers les tâches passées à partir d'une tâche actuelle.
Code %main (code principal, plus long, mais plus simple)
NTasksRepBeforeGoingBack=nan(length(data),1);
numTasksRepAfterSwitch=nan(length(data),1);
incrRep=0;
for lineNum=firstSwitchLineNum:length(data)
if data(lineNum)~= data(lineNum-1)
incrRep=0;
numTasksRepAfterSwitch(lineNum)=0;
else
incrRep=incrRep+1;
numTasksRepAfterSwitch(lineNum)=incrRep;
end
end
incrSucc=1;
NsuccessiveTasks(1)=1;
for lineNum=2:length(data)
if data(lineNum)~= data(lineNum-1)
incrSucc=1;
else
incrSucc=incrSucc+1;
end
NsuccessiveTasks(lineNum)=incrSucc;
end
for lineNum=secondSwitchLineNum:length(data)
if switchLines(lineNum)==1
NTasksRepBeforeGoingBack(lineNum)=NsuccessiveTasks(lineNum-1);
end
end
%Montre
NTasksRepBeforeGoingBack'
numTasksRepAfterSwitch'
Output
ans =
NaN NaN NaN 1 NaN NaN 3 NaN 2 1 1
ans =
NaN NaN 0 0 1 2 0 1 0 0 0
Compiler
Imaginez le cas où vous avez 100 fichiers séparés correspondant aux données de 100 participants
différents. Préférez-vous ouvrir-copier-coller-fermer-sauvegarder les 100 fichiers pour les coller les uns en
dessous des autres, ou utiliser un court programme pour faire ce travail ? Compiler des fichiers réfère à ce
travail d'automatisation consistant à réunir plusieurs fichiers en un seul fichier. Le programme suivant
permet par exemple de compiler trois fichiers contenant chacun le numéro du sujet, son âge en mois, le
6
numéro de l'essai, le numéro de l'image présentée à l'essai donné et le temps de réponse pour une image
donnée enregistré au moment d'un click de souris (il peut y avoir un ou plusieurs temps de réponse pour
une même image ou aucun, auquel cas le temps de réponse est nul ; lorsque l'image est cliquée plusieurs
fois, plusieurs lignes apparaissent avec le même numéro d'image, ce qui est le cas par exemple pour l'image
201 pour laquelle le sujet a cliqué deux fois). Le programme consiste à extraire automatiquement tous les
fichiers terminant par l'extension 'dta' d'un dossier choisi au départ. L'extension pourrait être '.xls' ou autre,
peu importe. L'avantage est de parcourir automatiquement le dossier afin de compter le nombre de fichiers
'... .dta', lire chacun des fichiers, et enlever la première ligne indiquant les noms de colonnes afin de n'avoir
plus qu'une tête de colonnes dans le fichier final avec le nom des variables. On profite ensuite des
nombreuses capacités de MATLAB pour exporter le fichier final sous différents formats (.xls, .csv, ...).
L'avantage d'un tel programme est de s'appliquer à n'importe quelle situation. Il suffit de changer quelques
paramètres au départ afin qu'il nomme ou renomme correctement les têtes de colonnes. Ce programme peut
aussi servir de base pour recoder au passage des variables (par exemple, faire une colonne du logarithme
des temps de réponse), mais nous conseillons toutefois de ne pas mélanger un programme qui compile avec
un programme qui recode, car dans ce cas, le programme n'est plus générique et ne s'applique plus à
d'autres données.
name ageMonths trialNum picNum RT_Click
1 295 1 229 2250
1 295 2 221 1609
1 295 3 201 2281
1 295 3 201 3219
1 295 4 239 1641
etc.
Code %Ce programme trouve tous les fichiers d'un même type localisés dans un
dossier. Tous ces fichiers sont ensuite lus et compilés en un seul
fichier. On utilise une matrice de type cell array pour mélanger des
chiffres et des chaînes de caractère.
%Efface les variables
clc
clear all
%Paramètres à choisir en fonction des données à compiler
headColumns={'name', 'ageMonths', 'trialNum', 'picNum', 'RT'};
nColumns=length(headColumns);
whereColumnsShouldBeNumbers=[2:5];
resultLocation = '/Users/fabien/DOCS/COURS/M2 Manuel
MATLAB/chap5data/';
nameNewFile='dataCompiled';
%Liste le nom des fichiers individuels
tic %Départ du chronomètre pour le programme en entier
tmpListOfFiles = dir(resultLocation); %Liste tous les fichiers situés
dans resultLocation, ainsi qu'une liste des propriétés des fichiers
tmpListOfFileNames={tmpListOfFiles.name};%On extrait des propriétés des
fichiers leur nom seulement
7
tmpNFiles=length(tmpListOfFileNames);%On comptabilise le nombre de fichiers listOfDataFiles={}; for tmpFileNum=1:tmpNFiles if isempty(findstr('dta', tmpListOfFileNames{1,tmpFileNum}))==0 %dir*.dta est une solution alternative à findstr ; ou encore mieux, utiliser par exemple filenames=ls('*.dta') listOfDataFiles=[listOfDataFiles,tmpListOfFileNames{tmpFileNum}]; end end Nparticipants=length(listOfDataFiles); %% Lecture des fichiers incrLine=0; datamissing=[]; for fileNum =1:Nparticipants tic %départ du chronomètre pour lire un fichier disp(['subject = ', num2str(fileNum)]) data_one_subject{fileNum}=textread([resultLocation listOfDataFiles{1,fileNum}],'%s'); % Une solution alternative est textscan. size_file=size(data_one_subject{fileNum},1); %On regarde s'il manque des données, en regardant si la division du nombre de mesures lues divisées par le nombre de colonne conduit à un reste non nul. La fonction mod donne le reste d'une division. if mod(length(data_one_subject{fileNum}),nColumns)~=0 datamissing=[datamissing,fileNum] %La variable datamissing accumule le numéro des fichiers qui posent problème. c'est une variable à consulter pour contrôler les fichiers. end incrementCell=nColumns; %On saute la première ligne (la tête des colonnes qui correspond au nom des variables). incrementCol=0; for lineNum=2:size_file/nColumns %sert également à sauter la première ligne incrLine=incrLine+1; for colNum=1:nColumns incrementCell=incrementCell+1; if colNum==1; subjectNameAnonymous=['subject' num2str(fileNum)];%On en profite pour rendre les données anonymes si ce n'est pas le cas. tmpData(fileNum,lineNum-1,colNum)={subjectNameAnonymous};%lineNum-1 respecte le saut de la première ligne else tmpData(fileNum,lineNum-1,colNum)=data_one_subject{fileNum}(incrementCell); end compiledDataWithoutHeadCol{incrLine,colNum}=char(tmpData(fileNum,lineNum-1,colNum)); end end toc
8
disp(' ')
end
%On récupère le nom des colonnes et on les place en haut du nouveau
tableau
for col=1:nColumns
compiledData{1,col}=headColumns{col};
end
for line=1:length(compiledDataWithoutHeadCol)
for col=1:nColumns
compiledData{line+1,col}=compiledDataWithoutHeadCol{line,col};
end
end
%%
%On EXPORTE le nouveau tableau compilé et on ajoute quelques notes
décrivant le travail effectué.
disp(' ')
disp('Export data to text and Excel files ...')
cell2csv([nameNewFile,'.csv'],compiledData,',')
cell2csv([nameNewFile,'.xls'],compiledData,'\t')
notes={'On indique ici des renseignements utiles pour soi-même, et on
peut donner des précisions utiles pour de futures simulations par
d'autres auteurs};
cell2csv([nameNewFile,'Notes.txt'],notes,'\t')
disp(' ')
disp('Total running time =')
toc %measures running time
Output
Au final, on obtient le fichier suivant :
name,ageMonths,trialNum,picNum,RT
subject1,295,1,229,2250
subject1,295,2,221,1609
subject1,295,3,201,2281
etc.
subject1,295,90,209,3766
subject2,285,1,567,4289
subject2,285,2,559,2391
etc.
subject2,285,89,511,4055
subject2,285,90,515,2934
subject3,287,1,372,2152
subject3,287,2,364,2961
subject3,287,3,344,2730
etc.
subject3,287,88,316,0
subject3,287,89,302,0
subject3,287,90,307,0
9
Extraire des informations numériques d'un fichier non organisé en tableau
Nous réutilisons ici la méthode précédente de compilation pour aller chercher automatiquement des valeurs
numériques dans des fichiers contenant à la fois du texte et des nombres qui ne sont pas organisés en
tableaux. Nous utilisons personnellement souvent ce type de fichier afin d'obtenir des statistiques
descriptives rapidement sans avoir à faire des calculs sur la base des données brutes organisées en tableau.
Le fichier brut du premier sujet ressemble à cela :
firstname familyname ageMonths trialNum stimulus response
xxx xxx 221 1 a a
xxx xxx 221 2 a a
xxx xxx 221 3 ag ag
xxx xxx 221 4 cf cf
xxx xxx 221 5 ahb ahb
xxx xxx 221 6 gad ecb
xxx xxx 221 7 edfa adfc
L'expérimentation consistait à effectuer une mesure d'empan classique. Des séries de lettres de longueur
croissante étaient présentées jusqu'à deux erreurs consécutives, avec deux essais par longueur. Dans ce
fichier, on remarque que le participant rappelle correctement les deux séries de 1 lettre, ainsi que les deux
séries de 2 lettres. On peut donc le gratifier d'un empan mnésique de 2. Pour être plus précis, étant donné
qu'il réussit aussi à rappeler "ahb" (au contraire de "gad" et "edfa"), on peut dire que son empan est égal à
2.5. Il serait injuste de dire que ce participant ne peut rappeler strictement que 2 lettres, et il serait tout aussi
faux de dire qu'il possède un empan de 3 puisque sa mémorisation de 3 éléments est fragile. Le programme
que nous avions conçu pour cette expérimentation résumait directement le score d'empan dans un fichier
annexe portant l'extension Misc.dta (Misc, pour Miscellaneous en anglais signifiant "divers"). Ce score
avait été calculé automatiquement en cumulant 0.5 par rappel correct.
Le fichier résumé data1_Misc.dta contient les informations suivantes :
Informations basiques + SPAN
------------------------------------------------------------------
Nom: xxx
Prénom: xxx
Age en mois: 221
Date ((attention, l'ordinateur peut fournir une date qui inverse mois et jours)) : 03-21-2012
SPAN = 2,5
------------------------------------------------------------------
Pour calculer l'empan moyen de l'échantillon de 60 participants, quel autre choix que d'ouvrir les 60
fichiers, lire le SPAN (i.e., l'empan), et le noter dans un tableur en face du numéro du participant. On peut
aussi en profiter pour noter son âge car toute partie méthodologique requiert de décrire l'échantillon. Le
programme qui suit a été élaboré en une trentaine de minutes, ce qui est beaucoup plus économique en
temps, et encore une fois, autant passer du temps à structurer votre pensée de façon algorithmique que
d'exécuter des tâches répétitives (et qui de plus, sont sujettes à des erreurs d'étourderie). Le programme
consiste comme dans la partie précédente à lister tous les fichiers, puis à les lire (en identifiant chacun des
champs séparés par des espaces). La lecture du premier fichier a la forme suivante dans la variable
data_one_subject{1}. On remarque que l'âge (en mois) est toujours situé sur le 13e champ (la
13e ligne) et le span sur l'avant dernière ligne. Le programme calcule ensuite grâce à la fonction
grpstats de la statisticstoolbox la moyenne et l'écart-type du span et de l'âge. On peut néanmoins se
passer aisément de cette fonction par l'utilisation des fonctions mean et std. Enfin, on dessine
l'histogramme des empans.
10
' Informations '
'basiques'
'+'
'SPAN'
'------------------------------------------------------------------'
'Nom:'
'xxx'
'Prénom:'
'xxx'
'Age'
'en'
'mois:'
'221'
'Date'
'((attention,'
'l'ordinateur'
'peut'
'fournir'
'une'
'date'
'qui'
'inverse'
'mois'
'et'
'jours))'
':'
'03-21-2012'
'SPAN'
'='
'2,5'
'------------------------------------------------------------------'
Code
%% Calcule l'empan mnésique pour Exp #2
%Reset
clc
clear all
%Data localisation
resultLocation = '/Users/fabien/DOCS/Articles/16-Mustapha 1
compression/DATA2/';
%Liste les fichiers de données
tmpListOfFiles = dir(resultLocation);
tmpListOfFileNames={tmpListOfFiles.name};
tmpNFiles=length(tmpListOfFileNames);
listOfDataFiles={};
for tmpFileNum=2:tmpNFiles
if isempty(findstr('Mis.dta',
11
tmpListOfFileNames{1,tmpFileNum}))==0 listOfDataFiles=[listOfDataFiles,tmpListOfFileNames{tmpFileNum}]; end end Nparticipants=length(listOfDataFiles); %Lit les fichiers, cherche l'empan et l'âge dans chaque fichier. spanVector=[]; ageVector=[]; for fileNum =1:Nparticipants disp(['subject = ', num2str(fileNum)]) data_one_subject{fileNum}=textread([resultLocation listOfDataFiles{1,fileNum}],'%s'); %Recherche l'empan et l'âge lastCellNum=size(data_one_subject{fileNum},1); decimalPosition=findstr(',',char(data_one_subject{fileNum}(lastCellNum-1))); spanString=char(data_one_subject{fileNum}(lastCellNum-1)); spanString(decimalPosition)='.'; span=eval(spanString); age=eval(char(data_one_subject{fileNum}(13))); if span < 2 %Recherche des données aberrantes disp(char(data_one_subject{fileNum}(7))) end spanVector=[spanVector,span]; ageVector=[ageVector,age]; end %Histogramme freq=hist(spanVector,5); bar(freq) set(gca,'XTickLabel',{'2' '2.5' '3' '3.5' '4'}); h = findobj(gca,'Type','patch'); set(h,'FaceColor','g','EdgeColor','w') xLabel('Span','FontSize',12); %Statistiques descriptives group=ones(1,Nparticipants); [meanSpan,stdSpan] = grpstats(spanVector,group, {'mean','std'})%utiliser les fonctions mean et std si vous n'avez pas la statisticstoolbox pour calculer grpstats [meanAge,stdAge] = grpstats(ageVector/12,group,
12
{'mean','std'})
Output subject = 1
subject = 2
subject = 3
...
subject = 59
subject = 60
meanSpan =
2.5417
stdSpan =
0.4897
meanAge =
21.2931
stdAge =
3.8097
Restructurer et agréger les données
La dernière section de ce chapitre concerne la restructuration et l'agrégation des données. L'objectif est
d'obtenir des tableaux résumés à partir de données brutes. Un exemple classique en psychologie cognitive
est de répéter les mesures pour x conditions afin d'obtenir des données plus robustes. On souhaite par
13
exemple mesurer le temps de réponse des sujets pour juger si un visage est attractif ou non en fonction du
sexe. Dans ce cas, on peut proposer 50 visages masculins et 50 visages féminins. On obtient 100 mesures
par sujet, mais pour simplifier les statistiques, on souhaite souvent réduire le tableau aux deux temps de
réponse moyens pour chacune des conditions. Si l'expérimentation comporte 20 participants, le tableau
final mesure ainsi 20 lignes (les participants) par 2 colonnes (les temps moyens pour chacune des deux
conditions). Cette réduction s'appelle l'agrégation des données (on dit aussi collapse en anglais pour faire
référence à un écroulement). La restructuration quant à elle, fait plus simplement référence au fait
d'inverser les lignes et les colonnes, une transformation appelée "transposition" dans Excel.
Les deux solutions que nous proposons pour l'agrégation des données, par ordre de préférence croissant,
sont l'utilisation des tableaux croisés dynamiques sous Excel et les méthodes Aggregate et Restructure
d'SPSS. Un excellent tutoriel de ces deux fonctions SPSS est donné par Lacroix & Giguère (2006), et il est
très utile d'ouvrir leur article pour suivre les étapes nécessaires à la restructuration d'un tableau, car SPSS
utilise un vocabulaire qui n'est pas nécessairement intuitif.
Concernant la première solution de restructuration des données grâce à Excel, on trouve la fonction
Tableau Croisé Dynamique à partir du menu "Insertion" avec une version Excel récente ou à partir du menu
Données pour une version Excel plus ancienne. Dans le fichier de départ suivant, on trouve respectivement
le numéro du sujet, le numéro de l'essai, le type d'essai (r, s, i ou d) et le temps de réponse (TR).
14
Le tableau dynamique suivant indique la moyenne des TR pour les conditions r, s, i et d. Nous avons
développé l'exemple le plus simple possible, mais nous aurions pu choisir des options plus complexes afin
d'obtenir les moyennes pour chacun des sujets.
Nous développons maintenant la solution SPSS, que nous préférons car elle évite entre autre les "glissés"
de souris un peu risqués d'Excel. Les données ci-dessous (capture 1) sont issues des résultats obtenus par
des participants à un test de mémoire à court-terme. Le nombre d’essais par sujet était de 50, et on peut
constater que pour un même sujet, il y a autant de lignes que d’essais réalisés. Ce tableau de données
compte donc 50 ! n (nbre de sujets) lignes. Si l’on réalise une analyse du temps de réponse (TR) en
fonction du type d’ordre de présentation (variable dénommé "type" dans le tableau, avec comme modalités
les valeurs r, s, i ou d) sur l’ensemble des données, le nombre de degrés de libertés sera élevé et les
résultats du test seront biaisés (en confondant la variance inter- et intra-individuelle). C’est pourquoi il est
pertinent de procéder à l’agrégation et à la restructuration des données afin d’obtenir une seule ligne par
sujet. Dans SPSS, la règle d'or est qu'un tableau doit respecter la contrainte que les données d’un sujet
doivent apparaitre sur une seule et même ligne. Un saut de ligne représente nécessairement une mesure
indépendante de la précédente. L'agrégation permet donc de calculer une valeur moyenne pour chacune
des manipulations (alors que les mesures ont été répétées pour chacune de ces manipulations pour obtenir
des résultats moyens plus exacts). La restructuration permet de transposer ces résultats moyens sur une
seule ligne.
15
Capture 1
Pour commencer, après avoir ouvert dans SPSS le fichier original de données, dans l’onglet « Données »,
choisissez l’option « Agréger ». Une nouvelle fenêtre s’ouvre dans laquelle vous pouvez sélectionner parmi
l’ensemble des variables (colonne de gauche) les critères d’agrégation de votre choix et les variables que
vous souhaitez analyser. Dans notre exemple (Capture 2) nous avons sélectionné « type » et « sujets »
comme critères d’agrégation (on agrège nécessairement par sujet si l’on veut obtenir une ligne par sujet)
ainsi que le temps de réponse « RT» et « accuracy » comme récapitulatifs de variable. Vous avez le choix
d’ajouter les variables agrégées à un ensemble de données actif, de créer un nouvel ensemble de données ne
contenant que les variables agrégées ou de créer un nouveau fichier ne contenant que les variables
agrégées. Nous conseillons la dernière option afin de préserver votre ficher de données original. Vous
pouvez alors renommer ce nouveau fichier, en veillant à le nommer de la façon la plus explicite possible.
En effet, vous risquez de générer autant de fichiers contenant des variables agrégées que vous aurez
d’analyses à effectuer. Si le nom du fichier reflète précisément son contenu, vous pourrez le retrouver plus
rapidement.
16
Capture 2
Dans notre exemple (Capture 3), on obtient pour chaque sujet une ligne par type d’ordre (notre critère
d’agrégation), soit quatre lignes par sujet correspondant aux moyennes obtenues pour chacun des ordres
possibles (au lieu de 50 lignes au départ). Ce résultat n'est pas suffisant car nous devons transposer ces
résultats en ligne en des résultats en colonne afin d’obtenir une seule ligne par sujet.
Capture 3
17
Pour obtenir une seule ligne par sujet, il faut procéder à une restructuration du tableau afin d’inverser les
lignes et les colonnes (opération aussi appelée transposition). Ainsi, au lieu d’avoir une seule colonne pour
les temps de réponse par exemple, on obtiendra quatre colonnes pour les temps de réponse correspondant
aux quatre ordres possibles. Pour procéder à cette opération, choisissez dans l’onglet « Données », l’option
« Restructurer… ». L’assistant de restructuration des données s’ouvre dans une nouvelle fenêtre et vous
offre trois possibilités de restructuration : restructurer les variables sélectionnées en observations,
restructurer les observations sélectionnées en variables ou transposer toutes les données. Dans notre
situation, afin de réorganiser l’ensemble des données de chacun des groupes d’observations sur une seule
ligne, nous avons sélectionné la seconde option (Capture 4).
Capture 4
Cliquez ensuite sur « suivant » pour sélectionner les observations à transformer en variables (Capture 5).
Vous devez pour cela sélectionner la ou les variable(s) d’identification (dans notre exemple, il s’agit des
sujets puisque nous souhaitons obtenir une seule ligne par sujet), la ou les variable(s) d’index (ici, le type
d’ordre de présentation).
18
Capture 5
Après avoir cliqué sur suivant, vous pouvez fermer l’assistant en cliquant sur « terminer » (Capture 6). Si
vous le souhaitez, le feuillet suivant vous permet de choisir dans quel ordre vous souhaitez que vos
colonnes soient organisées.
Capture 6
Contrairement à l’agrégation, la restructuration modifie directement votre tableau de données. Dans notre
exemple, le résultat est visible dans la Capture 7. Notre tableau comporte bien une seule ligne par sujet
avec pour chacune de nos deux variables, « accuracy » et « RT », quatre colonnes correspondant aux quatre
types d’ordre de présentation identifiés par les suffixes d, i, r et s.
19
Capture 7
Facteurs aléatoires
Ce point est complexe pour ceux n'ayant pas suivi de cours de statistiques avancées au niveau Master-
Doctorat, mais il existe une possibilité d'éviter la restructuration des données pour conserver
l'enregistrement d'essais successifs sur des lignes successives en choisissant des analyses statistiques avec
le facteur sujet comme facteur aléatoire (ou encore, d'utiliser les modèles mixtes, encore plus complexes ;
cf. Baayen, Davidson & Bates, 2008), dans SPSS par exemple. Les trois tableaux suivants illustrent le
paragraphe précédent, qui montre les étapes successives pour agréger et restructurer les données.
Facteur Essais Sujet Résultat
1 1 1 1
1 2 1 2
1 1 2 3
1 2 2 4
1 1 3 4
1 2 3 5
1 1 4 6
1 2 4 8
1 1 5 7
1 2 5 9
2 1 1 10
2 2 1 12
2 1 2 13
2 2 2 14
2 1 3 16
2 2 3 20
2 1 4 23
2 2 4 25
2 1 5 25
2 2 5 19
20
Après restructuration :
Condition 1 Condition 2
Essai 1 Essai 2 Essai 1 Essai 2
1 2 10 12
3 4 13 14
4 5 16 20
6 8 23 25
7 9 25 19
Après agrégation :
Résultat
Condition 1
Résultat
Condition 2
1.5 11.0
3.5 13.5
4.5 18.0
7.0 24.0
8.0 22.0
Néanmoins, on peut se passer de ces étapes en choisissant une ANOVA univariée avec le facteur sujet
comme facteur aléatoire, avec le premier tableau. L'analyse conduit à un F(1,4) = 85.6, p < .001; la valeur
et les degrés de liberté sont identiques avec une ANOVA pour mesures répétées appliquée au dernier
tableau après agrégation.
21
Chap 6. Des figures complexes et originales
Pour en apprendre le plus possible sur la manière de faire des figures mauvaises ou inversement, élégantes,
nous référons le lecteur au petit article de Wainer (1984). L'une de ces Figures (Minard, 1861), qui illustre
la retraite de Russie des troubles napoléoniennes (1812), parvient de manière ingénieuse à représenter 6
variables (l'espace, le temps, la température, l'effectif des troupes, le parcours des troupes, et le sens
aller/retour du parcours) sur une figure en deux dimensions. D'autres exemples montrent qu’il est possible
par des effets de manipulation d’axes, d'échelles, ou d'organisation des données (ordres alphabétiques
imposés par exemple) de modifier la lisibilité des figures et ainsi pervertir, selon des stratégies conscientes
ou non, leur lecture. On trouvera des exemples plus récents en consultant les références actuelles de
Wainer.
Le programme chap6.m répertorie une liste de codes chacun associé à une figure. Dans les rapports
scientifiques, "Figure" est le terme générique pour toute illustration qui n'est pas un tableau. Un graphe, un
diagramme, un schéma, une image, etc. sont considérés comme des figures, qu'on numérote selon l'ordre
d'apparition dans le texte (Figure 1, Figure 2, etc.). Comme tous les termes numérotés qui ressortissent à la
catégorie des noms propres, "Figure XX" doit toujours porter une majuscule.
Matrice de corrélation avec diagonale originale
Le premier exemple permet de réaliser une matrice de corrélation à partir de données aléatoires. En toute
logique, aucune corrélation ne doit apparaître dans la matrice puisque les données sont indépendantes les
unes des autres. La fonction randn est utilisée pour produire 3 colonnes de 50 scores z supposés
représenter 3 mesures différentes effectuées sur 50 participants. Le calcul de moyennes et des écart-types
permet juste de vérifier leur valeur autour de 0 et 1 respectivement. La figure produite est une matrice de 9
diagrammes de dispersion résultant du croisement des 3 variables (1-1, 1-2, 1-3, 2-1, 2-2, 2-3, 3-1, 3-2, 3-
3). Les corrélations sont égales à 1 lorsqu'une variable est corrélée à elle-même. Dans deux cellules
symétriques, les corrélations affichées ont la même valeur (par exemple, 1-2 et 2-1) puisqu’elles
correspondent à une même relation. En revanche, les diagrammes de dispersion ne sont pas identiques
selon que les variables sont placées sur l'axe des X ou des Y. C'est la raison pour laquelle, les diagrammes
situés en haut de la diagonale sont symétriques mais pas identiques à ceux situés en bas de la diagonale.
Pour les 3 variables, MATLAB produit une figure originale et concentrée en information, en remplaçant les
cases diagonales (non pertinentes) par les histogrammes de chaque variable.
Code
%% Matrice de corrélation
%Data
clear all
x=randn(50,3) %150 scores z tirés aléatoirement
%Moyennes
moyennes =mean(x) %Par défaut, les moyennes sont calculées
par colonne
grandeMoyenne=mean(mean(x))
std(x)%Ecart-type. std représente "standard deviation".
%Figure
plotmatrix(x, '*r') %Produit la matrice de corrélation avec
des points en étoile rouges. plotmatrix(x) est possible.
Output
x =
22
0.4364 -0.2506 0.6737
-0.5044 -0.1899 -0.6691
0.1021 -1.0329 -0.4003
1.1963 -0.3233 -0.6718
0.1203 0.7665 0.5756
-1.0368 1.7447 -0.7781
etc.
moyennes =
0.0052 0.2495 0.0741
grandeMoyenne =
0.1096
ans =
0.9118 1.1094 1.1554
>>
>>
Diagrammes de dispersion avec cohortes
Pour un simple diagramme de dispersion entre 2 variables, on choisira plutôt la commande scatter.
Nous ne développons pas d'exemple utilisant scatter qui ne s’accorde pas aux cas des figures
complexes. Un peu plus sophistiquée, la fonction gscatter de la Statistics Toolbox permet de
superposer les diagrammes de dispersion de différents groupes. Afin de savoir si cette toolbox est installée
dans votre version, tapez ver dans la fenêtre de commandes qui renverra un descriptif précis de votre
version MATLAB accompagné de la liste des toolboxs installées.
23
Code
ver
Output
-------------------------------------------------------------------------------------
MATLAB Version 7.10.0.499 (R2010a)
MATLAB License Number: XXX
Operating System: Mac OS X Version: XXX
Java VM Version: Java 1.5.0_30-b03-389-9M3425 with Apple Inc...
-------------------------------------------------------------------------------------
MATLAB Version 7.10 (R2010a)
DatapixxToolbox Version 0.9, Aug
Bioinformatics Toolbox Version 3.5 (R2010a)
Image Processing Toolbox Version 2.2.2 (R12)
Image Processing Toolbox Version 3.1 (R12.1)
Netlab Toolbox Version 3.3.1
Psychtoolbox Version 3.0.8 9 October
Statistics Toolbox Version 7.3 (R2010a)
>>
Il est possible d’utiliser la fonction gscatter sans spécifier d’option de couleur ou de marqueurs, pour
cela il suffit d’entrer : gscatter(x,y,group), les paramètres par défaut sont alors appliqués.
Mais il est possible d’accéder aux options de couleurs et de marqueurs. Dans l'exemple suivant, on choisit
k, r, o, et s comme paramètres de la fonction (en plus des variables x, y et group). En tapant help dans la
fenêtre de commande, l’ordre dans lequel il faut lister les paramètres s’affiche. Ici, la fonction attend
d'abord la liste de couleurs, ensuite la liste des marqueurs. Etant donné qu'on souhaite que le diagramme
représente deux nuages de points (deux cohortes), 'kr' signifie qu'on attribue la couleur black (k) au
premier groupe et red au second (r). D’une manière générale, dans MATLAB, chaque couleur est associée
à une lettre précise. Par intuition, on devine que g est associé à green, sans avoir recourt à une page d'aide.
Pour attribuer respectivement les marqueurs cercles et carrés à chaque groupe, on utilise la chaîne'os'
dont les deux lettres représentent respectivement le cercle (o, par similarité de forme avec le cercle) et le
carré (s pour squares). Si on souhaite paramétrer les marqueurs mais conserver les couleurs par défaut, on
écrit gscatter(x,y,group,'','os').
Code %% Diagrammes de corrélation avec plusieurs cohortes de
points
clc
x=[1:10,1:10]
y=[[1 2 3 4 4 5 4 6 7 8],[2 3 5 6 8 8 9 12 10 13]]
group=[ones(1,10), 2*ones(1,10)]
gscatter(x,y,group,'kr','os',7,'off','khrekjwhrkejh','lkjfd
lskjflksjfds') %à essayer
%gscatter(x,y,group,'','os') %à essayer
%gscatter(x,y,group) %à essayer
Output
24
Graphes à deux axes Y
L'exemple suivant illustre la possibilité de faire une figure contenant deux axes Y, l'un à gauche, l'autre à
droite. Cela permet de superposer deux phénomènes qui se rapportent à une même variable X. La difficulté
consiste à récupérer les paramètres de sortie de la fonction afin de pouvoir modifier la figure produite par
défaut. Nous avions vu dans le premier chapitre que l'écriture [x,y]=maFonction(paramètre1) signifie que
la fonction maFonction renvoie deux résultats (x et y) après avoir traité le paramètre1. Cela pourrait être le
temps mis pour exécuter la fonction (x) et le résultat de la fonction (par exemple paramètre1 est la
température en degrés Celsius, et y la température en degrés Fahrenheit). Ici, [AX,H1,H2] sont des
paramètres de sortie qui représentent respectivement les axes (AX) et les divers objets dessinés dans la
figure (H1, pour les objets correspondant à l'axe Y de gauche, et H2 pour celui de droite). AX, H1 et H2
sont des numéros uniques (appelés des handles) attribués à des ensembles graphiques qui permettent
d'accéder à leurs propriétés (couleurs, emplacement, etc.). Pour récupérer par exemple les propriétés d'H1,
on utilise son numéro ou simplement la variable elle-même en utilisant get(H1). Le résultat de cette
commande est décrit en détail juste après le code et la figure ci-dessous...
Code
%% Figure incluant deux axes Y différents
TR=[1500 800 600 650 500 550] %temps de réponse
propCorrect=[.2 .2 .5 .6 .9 .9] % proportion de réponses
correctes
blockNum=[1:6]
[AX,H1,H2]=plotyy(blockNum,TR,blockNum,propCorrect,'plot','
plot')
set(H1,'LineStyle','--','color','blue')
set(H2,'Marker','s')
set(get(AX(1),'Ylabel'),'String',' RT', 'Fontsize', 14)
set(get(AX(2),'Ylabel'),'String','Prop.
Correct','Fontsize', 14)
set(get(gca, 'XLabel'), 'String','Block Number',
'Fontsize', 14)
25
Output
Code (en laissant la figure ouverte, sans quoi la commande suivante ne fonctionnera pas)
propH1 = get(H1).
Output
>> proprietes = get(H1)
proprietes =
DisplayName: ''
Annotation: [1x1 hg.Annotation]
Color: [0 0 1]
LineStyle: '--'
LineWidth: 0.5000
Marker: 'none'
MarkerSize: 6
MarkerEdgeColor: 'auto'
MarkerFaceColor: 'none'
XData: [1 2 3 4 5 6]
YData: [1500 800 600 650 500 550]
Etc.
La commande get(H1)permet de récupérer les propriétés de H1 ne peut fonctionner que si l'on crée
une nouvelle variable, par exemple "propH1" dans l'exemple suivant. Le résultat indique une liste de
propriétés modifiables. Par exemple, "Marker: 'none' signifie qu'aucun marqueur n'est défini pour la courbe
des proportions correctes. Nous aurions obtenu un résultat identique pour H2 si nous n'avions pas utilisé la
commande set(H2,'Marker','s') qui nous a permis d'attribuer à la propriété 'Marker' de la
courbe H2 le paramètre square représenté par s. Pour conclure sur ce point applicable à toute figure, Get
permet d'accéder aux propriétés, et Set de les modifier. Grâce à ces deux commandes, il est possible de
changer tous les détails d'une figure, que ce soit la taille des polices, l'épaisseur des traits, le type de trait, la
couleur de fond, la position des légendes, etc.
26
Figures multiples juxtaposées
La commande subplot est très utile pour juxtaposer plusieurs figures. On peut imaginer par exemple
vouloir afficher les histogrammes de trois échantillons dans un espace divisé en trois parties nommées A),
B), et C). L'avantage consiste à limiter le nombre de fichiers à sauvegarder, à copier-coller, etc. Par ailleurs,
cette méthode règle parfaitement l'espacement entre figures. L'alternative consiste à produire trois
histogrammes dans un logiciel statistique, puis de les copier-coller dans un logiciel de bureautique en
réglant l'espacement de façon artisanale. Utiliser MATLAB permet un gain de temps indéniable et la
précision du placement des sous-figures est garantie.
Dans le code suivant, la première figure est délimitée en trois espaces sur trois lignes et une colonne grâce à
la fonction subplot(3,1,fig). La variable fig permet le positionnement de la figure tracée
dans l'espace. Cette commande doit être placée avant la figure demandée (ici un histogramme avec la
fonction hist).
Code
%% Figures contenant de multiples sous-figures
clc
clear all
%Montre 3 histogrammes
figure(1)
for fig=1:3
x=randn(50,1)
subplot(3,1,fig)
hist(x)
end
Output
27
La seconde portion du code est relative à un tout autre exemple qui consiste à afficher un grand nombre de
figures qui ne sont pas nécessairement des graphiques de statistiques. Ici, nous souhaiterions afficher 64
stimuli images enregistrés dans un dossier. La finalité est similaire au cas précédent dans le sens où la
fonction subplot remplace ce qu'on peut faire avec un logiciel de dessin avec un gain de temps
considérable. La fonction imread est utilisée pour charger une image. Il suffit juste d'indiquer à cette
fonction l'emplacement et le nom du fichier image à charger. La commande
folderName='.\chap6pic\' assigne à la variable folderName le nom du dossier
dans lequel aller chercher l'image (si vous utilisez un mac, remplacez les \ par des /). La boucle permet
de changer le nom de l'image avec la commande fileName=strcat('fig-
',num2str(fig),'.jpg'). Au premier passage dans la boucle, fig étant égal à 1,
strcat concatène (assemble bout à bout) 'fig-','1','.jpg' après que num2str ait
transformé le chiffre 1 en un caractère '1'. Il en résulte la chaîne 'fig-1.jpg'. Noter que nous
aurions pu utiliser simplement ['fig-','1','.jpg'] pour concaténer les trois parties, mais
l'utilisation de num2str ne le permet pas. En revanche, cette simplicité est utilisée pour
[folderName,fileName]) qui permet de former la chaîne './chap6pic/fig-
1.jpg'.
Au final, on accède à chacun des 64 espaces organisés en 8 colonnes et 8 lignes dans le sens de la lecture
grâce à la valeur fig. Lorsque fig est égal à 9, nous sommes sur l'emplacement correspondant à la
seconde ligne et la première colonne, puisque la première ligne correspondait aux 8 premiers
emplacements. Le résultat est l'affichage parfaitement régulier des 64 stimuli utilisés dans une
expérimentation. Avec la même méthode, on peut faire un patchwork de tout et n'importe quoi...
Code
%Montre 64 stimuli enregistrés sous le dossier chap6pic
figure(2)
folderName='./chap6pic/'
for fig=1:64
fileName=strcat('fig-',num2str(fig),'.jpg');
x=imread([folderName,fileName]);
subplot(8,8,fig);
image(x)
axis off
end
Output
28
Le dernier exemple utilisant la fonction subplot permet de tracer une même distribution théorique selon un
paramètre augmentant progressivement. On prend en exemple la distribution binomiale calculée
automatiquement par la fonction binopdf. On augmente ici la probabilité p de .1 à .8, et cette probabilité
est automatiquement associée au titre de chaque sous-figure. Ici, l’astuce est d'utiliser la fonction
linspace permettant de partager en intervalles égaux la fourchette de .1 à .8. Dans l'exemple, on décide
de montrer 18 distributions faisant varier progressivement la probabilité p de .1 à .8. Les 18 écarts réguliers
de .1 à .8 sont calculés automatiquement. Ensuite, on choisit de montrer uniquement 8 distributions faisant
varier progressivement la probabilité p de .1 à .8.
%% Montre 18 distributions normales théoriques pour p = .1
à p =.8 et N = 20
figure(3)
clc
clear all
N =20
nDistrib=18
p=linspace(.1, .8,nDistrib)
x=[0:N]
for distribNum=1:nDistrib
P=p(distribNum)
29
Y = binopdf(0:N,N,P);
subplot(2,nDistrib/2,distribNum)
bar(x,Y)
axis([0 N 0 .4])
string=['p = ' num2str(P)]
xlabel(string)
end
Output
Le même code avec nDistrib=8 génère :
Ajout de texte
Dans l'exemple nous allons construire une représentation graphique montrant la diminution de temps de
réponse à une tâche donnée en fonction de l’entraînement, une baisse souvent représentée par une loi de
30
puissance en psychologie. Ici, on manipule seulement le paramètre b, qui représente la vitesse avec laquelle
les temps de réponse vont diminuer jusqu'à une performance plancher égale à 200ms. L'intérêt ici est de
prévoir trois types de courbes :
curves={'ko-', 'bx:', 'rv--'}.
Par exemple, pour la seconde courbe, 'bx:' code la couleur bleue (b), des marqueurs en croix (x) et
des traits pointillés (:). Lorsqu'on veut retrouver l'aspect de la courbe correspondant à la valeur b
(bValue), on utilise curveNum = find(bValues==bValue) qui attribue à
curveNum la valeur 2 lorsque bValue = .5 par exemple. Ensuite, pour le texte, on réutilise
curves{curveNum}(1) dont on prend le premier élément pour retrouver la couleur. Si
curveNum = 2 alors le premier élément de 'bx:' est 'b' indiquant que le texte doit être en
bleu.
Code
%% Power law
clc
ASYMPTOTE =.200
bValues=[.3 .5 .8];
learningTrialNumbers=[0:50];
curves={'ko-', 'bx:', 'rv--'}
for bValue=bValues
Y=ASYMPTOTE+ learningTrialNumbers.^-bValue;
curveNum=find(bValues==bValue)
plot(Y,curves{curveNum});
hold on
text(20,Y(20)+.05,['b = ',
num2str(bValue)],'color',curves{curveNum}(1));
end
axis([0 X(end) ASYMPTOTE Y(1)]);
Output
31
Références Bibliographiques BAAYEN, R. H., DAVIDSON, D. J., & BATES, D. M. (2008). Mixed-Effects Modeling with Crossed
Random Effects for Subjects and Items. Journal Of Memory And Language, 59, 390-412. CAIRNS, P. & COX, A. (Eds) (2008) Research Methods for Human-Computer Interaction. Cambridge,
MA : Cambridge University Press. LACROIX, G. L., & GIGUÈRE, G. (2006). Formatting data files for repeated-measures analyses in SPSS:
Using the Aggregate and Restructure Procedures. Tutorials in Quantitative Methods for Psychology, 2, 20-26.
MATHY, F. (2006). Elégance, complexité et subtilités de la formalisation des plans expérimentaux.
Bulletin de Psychologie, 59 (2), 187-193. NOËL, Y. (2013). Psychologie statistique avec R. Paris : Springer PASHLER, H. & HARRIS, C. (2012). Is the replicability crisis overblown? Three arguments examined.
Perspectives on Psychological Science, 7, 531-536. PASHLER H., WAGENMAKER, E.-J. (2012). Editors’ introduction to the special section on replicability
in psychological science: A crisis of confidence? Perspectives on Psychological Science, 7, 528–530.
REY, Arnaud (2012). Psychologie cognitive expérimentale. Paris: PUF. ROSENBAUM, D. A. (2007). MATLAB for behavioral scientists. Mahwah, NJ: Lawrence Erlbaum
Associates. WAINER, H. (1984). How to Display Data Badly. The American Statistician Volume 38, Issue 2, pp. 137-
147. WETZELS, R., RAAIJMAKERS, J. G. W., JAKAB, E., & WAGENMAKERS, E.-J. (2009). How to
quantify support for and against the null hypothesis: A flexible WinBUGS implementation of a default Bayesian t test. Psychonomic Bulletin & Review, 16, 752-760.
1
Chapitre 8. Principes de la modélisation
Au cœur des sciences cognitives, au delà des nombreuses disciplines qui travaillent de concert
afin de décrire la formation des connaissances, on trouve un quadruplet fondamental de
méthodes : la conceptualisation, l'expérimentation, la modélisation et la simulation, la dernière
étant la plus fortement caractérisée par l'essor de l'informatique. La conceptualisation est une
mise en forme essentiellement verbale visant la description précise des causes, du fonctionnement
ou de la structure d'un phénomène (observé ou attendu). La conceptualisation peut s'appliquer à
différents niveaux, que ce soit la description d'un mécanisme mental de haut niveau tel qu'un
raisonnement précis dans un contexte donné, ou l'explication de bas niveau du fonctionnement
cérébral telle que l'idée qu'un déséquilibre de la dopamine dans le cerveau puisse être à l'origine
des troubles de l'attention chez l'enfant. Une conceptualisation peut se réduire au simple lien entre
plusieurs variables sans qu'aucune causalité ne soit imputée à l'une d'elles. Par exemple, la théorie
des états mentaux inversables (Reversal theory) présuppose que des individus peuvent alterner
entre des états mentaux complètement inversés selon leur état d'esprit à un moment t, ou que
plusieurs individus peuvent se comporter de façon complètement inverse dans un même contexte
du fait de leur personnalité (Kerr, 1999). Les états téliques et paratéliques illustrent bien ce
phénomène de polarité. Un état télique correspond à la focalisation sur un but alors qu’un état
paratélique se caractérise par la focalisation sur les moyens d’y parvenir. Une personne dans un
état télique perçoit son objectif comme fondamental et les moyens pour y parvenir sont
secondaires. Tout obstacle est perçu de façon négative, le travail à fournir pour atteindre l'objectif
est vécu comme douloureux et la moindre contrariété est source d'anxiété. L'état paratélique
considère que les moyens sont à investir en premier lieu, de façon à ce que l'objectif puisse être
atteint de façon agréable. La personne paratélique est orientée sur l'activité elle-même, et tout ce
qui est fait au cours du cheminement pour atteindre un but est vécu avec plaisir. L'objectif est
même parfois arbitraire, et posé au départ comme une simple raison de s'engager dans une
activité. De ce fait, la personne dans un état paratélique peut être perçue comme moins sérieuse
que celle dans l'état télique. Les surprises et les sensations sont les bienvenues, contrairement aux
attentes de la personne télique. On retrouve aisément cette distinction chez les personnes qui
pratiquent le sport pour le plaisir ou pour gagner car pour les uns, jouer sans la perspective de
gagner ne permet pas de pratiquer un sport correctement, alors que pour les autres, un adversaire
voulant absolument gagner semble passer à côté de l'essentiel du plaisir procuré par la pratique du
sport. Ces conceptualisations peuvent être assimilées à une théorie dont on attend qu'elle puisse
produire des hypothèses testables par l'expérimentation. Par exemple, la théorie peut prédire
qu'une personne télique peut se sentir relaxée dans le cas où elle ressent un plaisir assez faible
pendant son activité, alors que la personne paratélique ressentira un ennui profond lorsque son
éveil physiologique est faible. Au contraire, si les sensations sont intenses, la personne télique
ressentira une forme d'anxiété pendant que celle paratélique sera en pleine euphorie. D'autres
variables, de type binaire également, peuvent être ajoutées pour prédire des états mentaux
doublement inversables, comme le fait de présenter au départ un caractère conformiste ou
marginal, etc.
2
La différence entre conceptualisation et modélisation se situe dans la mathématisation. La
description des états téliques et paratéliques ne permet ici de mesurer aucune relation précise
comme par exemple le passage d'un état à un autre. Rien n'est dit par exemple sur le type de
fonction (exponentielle, logarithmique) qui relie deux variables. Par exemple, le passage des états
Relaxation à Anxiété est arbitrairement négativement exponentiel, alors que le passage de l'ennui
à l'état d'excitation est arbitrairement logarithmique. Nous avons volontairement choisi ces deux
types de courbes (à la différence de la théorie originale) afin de montrer l'absence de lien précis
entre les états. Aucune équation n'est formalisée ici, ce qui néanmoins peut être une aubaine pour
la diffusion d'une théorie car il paraît qu'on perd la moitié des lecteurs à chaque fois qu'on écrit
une équation ! L'exemple pris ici minimise volontairement la portée de la théorie et nous invitons
le lecteur intéressé à parcourir la littérature récente sur le sujet, qui ne manque pas d'apporter des
prédictions précises.
Puisque l'expérimentation vise la manipulation des variables, elle peut naturellement s'appuyer
sur une conceptualisation afin d'induire un effet expérimental. Pour rappel, l'expérimentation
suppose que la variable dépendante (la mesure) est fonction de la variable indépendante (le
facteur), une relation que l'on peut écrire VD = f(VI). Le moyen de s'en souvenir est que la
variable dépendante "dépend OU est fonction de" la variable indépendante (qui ne dépend de rien
dans le contexte isolé de l'expérimentation). Dans l'exemple pris précédemment, on peut tenter de
maintenir constante l'intensité d'une sensation dans un jeu vidéo afin de voir l'effet sur des
personnes au préalable identifiées comme téliques ou paratéliques. La variable dépendante,
autrement appelée mesure, peut simplement viser à connaître l'état (excité ou relaxé) de la
personne à l'issue du jeu. Les statistiques subséquentes serviront à établir si le facteur a induit une
différence significative entre les personnes téliques et paratéliques.
L'objectif ici n'est nullement de s’attarder la méthode expérimentale, mais de montrer comment
passer de la conceptualisation à la modélisation. De façon péjorative, on pourrait dire qu'une
conceptualisation est une simple intuition, qui mérite une formalisation plus précise, encore une
fois, fondée sur des équations mathématiques La simulation est encore plus complexe que le
modèle, dans le sens où elle cherche à faire vivre le modèle. La modélisation est statique, et la
simulation est dynamique. Nous reviendrons sur ce point plus complexe après avoir donné
quelques exemples de modèles. Nous commençons par développer quelques exemples de
modèles qui semblent gouverner des phénomènes divers tels que la vitesse de reproduction des
animaux, la disposition des feuilles sur une tige, la présence de parastiches (i.e., les motifs
spiralés) dans les fleurs de tournesol, etc.
3
Conceptualiser la reproduction des lapins peut commencer par le constat qu'ils semblent se
reproduire très rapidement. Notez qu'on ne dit pas qu'ils semblent se reproduire de façon
exponentielle, ce qui serait déjà la signature d'un modèle. Un modèle classique de cette
reproduction est la suite de Fibonacci, posant les deux constantes et l'équation suivantes :
U0 = 1; U1 = 1; Un+2 = Un+1 + Un,
Cette suite produit la série de nombres :
1, 1, 2, 3, 5, 8, 13, 21, 34,
selon les calculs simples,
1 +1 = 2,
1 + 2 = 3
2 + 3 = 5, etc.
4
La raison pour laquelle cette suite décrit bien la croissance du nombre de lapins est qu'1 couple de
lapins (nommés a et b) qui se regardent dans le blanc des yeux ne génère rien d'autre que ce
même couple de lapins (a et b). Cela explique déjà les deux premiers 1 de la suite ! Ce couple de
lapin entreprend assez rapidement d'avoir un couple de lapereaux (c et d), qui en première
génération sont trop jeunes pour être fertiles. Cela explique la présence de 2 couples. A la
génération suivante le premier couple engendre un nouveau couple de lapereaux (e et f) pendant
que les deux premiers lapereaux (c et d) atteignent l'âge de procréer, ce qui fait 3 couples. A la
génération suivante, le premier couple (a et b) continue d'engendrer un nouveau couple de
lapereaux (g et h), c et d procèdent à leur première contribution à la surpopulation (i et j), tandis
que e et f arrivent en âge de procréer, ce qui fait 5 couples au total. Tout en prédisant assez bien le
rythme de croissance de la population de lapins (voir Figure suivante), le modèle ne prend pas en
compte les décès (pourtant plus que probables) des lapins dans l'histoire, ce qui illustre
parfaitement le fait qu'un modèle est souvent simplifié.
1 2 3 4 5 6 7 80
5
10
15
20
25
Reproduction
Effectif de c
ouple
s d
e lapin
s
Un exemple de modélisation d'un phénomène précisément exponentiel est la loi de Moore qui
indique que la puissance des ordinateurs (à coût constant) double tous les 18 mois. Elle est assez
bien vérifiée depuis plus de 40 ans (Delahaye, septembre 2013). C'est une loi bien plus précise
que de remarquer naïvement "que le monde progresse", que nous pourrions assimiler à une forme
de proto-concept. Toutes les lois ne sont pas mathématisées. Il vous arrive peut-être de vous dire
que vous choisissez toujours la mauvaise file (sur une route ou dans un supermarché). Il s'agit de
la fameuse malédiction de la mauvaise file que tout le monde a cru connaître un jour ou l'autre.
Elle s'explique plus ou moins sérieusement par la loi de Murphy dite loi de l’emmerdement
maximum, postulant que "Si ça peut mal se passer, cela se passera mal. Il n’y a donc rien
d’étonnant à se retrouver toujours dans la mauvaise file." (Delahaye, mai 2012).
Revenons vers la suite de Fibonacci pour en montrer son applicabilité à la description d'autres
phénomènes naturels. La bifurcation des branches suit une structure similaire à la suite de
Fibonacci. Dessinez une grande branche numérotée 1, que vous laissez grimper sur votre feuille
sans plus jamais y retoucher. En bas de cette première branche, opérez une première bifurcation à
droite de la branche numéro 2, et sur cette seconde branche une 3e à gauche, puis une 4
e à droite
5
un peu plus haut. Sur la 3e, on peut faire une 5
e bifurcation à gauche, puis une 6
e à droite de la 3
e,
une 7e à droite de la 4
e, puis une nouvelle à gauche de la 5
e. A gauche, on retrouve la suite 1, 1, 2,
3, 5 et 8. Ces nombres expliquent le nombre d'embranchements à chaque poussée de la plante.
L'arbre dessiné dans la figure ci-dessous semble assez naturel, et dans tous les cas, certainement
plus proche de la réalité qu'un arbre binaire se scindant en deux branches à chaque poussée (1, 2,
4, 8, 16) dont le rendu est trop symétrique. On remarque qu'un point essentiel du modèle est de
permettre une reproduction d'une structure réelle.
La suite de Fibonacci est également liée au nombre d'or, que l'on retrouve en divisant deux
nombres consécutifs de cette suite, par exemple, 3/2 = 1.5, 5/3 = 1.66, 8/5 = 1.6, 13/8 = 1.63,
21/13 = 1.62, 34/21 = 1.61, etc. Remarquez que plus les deux nombres que l’on divise sont
grands, plus le résultat s’approche du nombre d’or. La proportion d'or est en effet déterminée par
deux chiffres consécutifs a et b lorsque (a + b)/a = a/b. On peut alors définir sur la base de ce
nombre d’or, le rectangle d'or, la spirale d'or et l'angle d'or. On retrouve ce nombre d'or dans des
phénomènes naturels comme par exemple la direction que prennent les feuilles poussant le long
d'une tige et leur permettant la meilleure exposition au soleil, phénomène auquel s’intéresse
exclusivement la phyllotaxie. La spirale d'or décrit à merveille l’organisation du coquillage
nautile ou de certaines galaxies. De même, l'angle d'or décrit la position des graines dans la fleur
de tournesol, la pomme de pin ou l'ananas.
Il est souvent compliqué d'expliquer pourquoi le nombre d'or s'applique si bien à la nature, mais
nous souhaitons montrer en guise d'exemple que la modélisation par ce nombre permet de
reproduire le cœur de la fleur de tournesol. Le cœur de la fleur de tournesol est formé d'un
ensemble d’unités voisines organisées en forme d’hélices, des parastiches, qui peuvent être
directes ou inverses selon qu'elles ont tendance à tourner vers la gauche ou vers la droite. Cette
organisation recoupe très bien deux nombres consécutifs de la suite de Fibonacci, le plus souvent
21 partant vers la droite et 34 partant vers la gauche. Au croisement des parastiches apparaît une
6
graine. Le site web http://tpe.tournesol.free.fr/tournesol.htm, qui existe depuis de nombreuses
années (parmi d’autres ressources électroniques ou papier sur le même sujet), illustre
parfaitement la raison de ce positionnement particulier des graines, qui est principalement liée à
la satisfaction de contraintes spatiales. En effet, il semble que les graines apparaissent de façon
régulière autour du cœur en fonction de l'angle d'or, puis suivent leur progression vers l'extérieur
du cœur au fur et à mesure que la fleur grandit. Le site web fournit une modélisation qui permet
de régler l'angle d'apparition des graines. Ci-après, nous indiquons quelques captures d'écran de la
simulation que l'on peut obtenir sur le site, étape par étape, via les boutons "Suivant" jusqu'à
arriver dans le simulateur qui permet de régler de nombreux paramètres comme la vitesse
d'éloignement des graines. On remarque dans la première capture d'écran un angle d'or entre la
première graine apparue à droite et la seconde en bas, puis un second angle d'or entre la graine de
gauche en bas et celle en haut commençant à émerger. Le processus continue ensuite d'une façon
qui paraît anarchique, puis l'arrangement en parastiches est de plus en plus visible. Remarquez
que les graines sont condensées au maximum au cœur de la fleur, alors qu'une très légère
modification de l'angle aboutit à la dernière capture, dont la fleur contient des graines bien plus
espacées malgré son aspect certes symétrique.
L'exemple de la fleur de tournesol montre de la manière la plus convaincante que l'aboutissement
de la modélisation est la simulation, c'est à dire la possibilité de reconstruire l'objet décrit.
Il est nécessaire de saisir la distinction entre la pensée formelle et l'intuition lorsqu’on entreprend
une démarche de modélisation. On peut construire un navire sur la simple intuition mais il n'est
7
pas certain qu'il soit insubmersible. En revanche, un calcul mathématique expert permet de tester
la flottaison avant d’entreprendre la construction du navire. Voyons maintenant quels sont les
principes de la modélisation en étudiant la solution d'Erasthotène au calcul de la circonférence de
la terre (Hunt, 2007). Il y a plus de 2000 ans, ce directeur de la bibliothèque d'Alexandrie,
mathématicien géographe, eu l'idée d'utiliser l'hypothèse que les rayons du soleil sont parallèles
pour calculer la circonférence. En ayant eu connaissance que le soleil se voyait au fond d'un puits
dans la ville de Syène à une époque précise de l'année (que l'on appelle maintenant le solstice),
Erasthotène en conclut que les rayons du soleil étaient parfaitement perpendiculaires à la surface
et devaient pointer vers le centre de la terre. En faisant la supposition que les rayons du soleil sont
parallèles, il en déduisit que l'angle alpha (entre Alexandrie et le puits de Syène) pouvait être
retrouvé à la surface en mesurant l'angle formé par l'ombre. Ayant mesuré que cet angle était égal
à un cinquantième de cercles, il multiplia la distance Syène-Alexandrie par cinquante pour arriver
à l'estimation d'environ 40.000 km. L'erreur d'estimation est évaluée à environ 1%, ce qui avec les
moyens de l'époque est assez surprenant.
La mathématisation du problème de la mesure de la circonférence de la terre par Erasthotène
illustre quelques principes élémentaires. Le premier est qu'un modèle est une simplification d'un
phénomène. La terre n'est pas une sphère parfaite et les rayons du soleil ne sont pas parfaitement
parallèles. Sans cette simplification, le scientifique reste crispé sur la complexité de la réalité et
n'envisage aucun calcul possible. Mais plus intéressant encore, le rasoir d'Occam, sur lequel nous
reviendrons plus tard, indique qu'un modèle a plus de chance d'être correct lorsque le modèle est
le plus simple possible. Le deuxième principe est que l'analogie entre les symboles et le monde
réel doit être explicite. C'est le cas ici pour les villes et la terre qui sont représentées sur la figure.
Un troisième principe est que le modèle tolère une marge d'erreur, et qu’en ce sens il n'est qu'une
approximation de la réalité. Cela ne doit pas être confondu avec le premier principe qui fait
référence à la structure du modèle et non aux mesures. Les mesures d'Erasthotène n'ont pas eu
vocation à être exactes (ni celle d'alpha, ni la distance Alexandrie-Syène), seulement les plus
précises possibles. Un dernier principe est qu'un modèle ne peut pas être simplement accepté ou
8
refusé de façon dichotomique. On estime simplement la similarité produite avec le monde qu'il
tente de décrire. Lorsque c'est possible, on calcule un ajustement du modèle (produisant des
données artificielles) aux données réelles grâce à des statistiques. C'est plutôt la proximité de la
correspondance qui est jugée et on suppose que le meilleur modèle est celui prédisant le mieux les
données. C'est très simple à comprendre avec la météorologie grâce à laquelle on souhaite
pouvoir prédire le temps de la façon la plus fine possible. N'être pas convaincu des fondements
théoriques d'un modèle prédisant pourtant avec une quasi perfection le temps n'aurait aucun sens.
Dans le domaine de la météorologie, c'est la performance du modèle qui est jugée.
La mesure d'Erasthotène est unique, mais on aurait pu essayer plusieurs distances de villes
associées avec plusieurs angles alpha. Dans ce cas, il aurait obtenu une distribution de mesures
dont il aurait pu simplement retenir la moyenne, en considérant les mesures de part et d'autre de
la moyenne comme des erreurs de mesure. Par exemple, si vous mesurer le poids de votre
baguette de pain tous les jours, vous remarquerez qu'il est centré autour de 250 grammes. C'est
une expérience qu'avait conduite Poincaré en son temps, démontrant qu'au delà des fluctuations
naturelles, le poids du pain tendait vers un peu moins d'un kilogramme aux dépends de l'acheteur.
Les fluctuations aléatoires de mesure sont banales et acceptées en science.
La mesure unique d'Erasthotène est également limitée à une seule prévision, alors qu'en
météorologie, une fois qu'un modèle a été capable d'ajuster correctement plusieurs jours de
données météorologiques, on peut tester sa capacité à prédire le temps le lendemain. Un modèle
est donc caractérisé par des données en entrée (le temps au jour j) et des données en sortie (le
temps au jour j + 1), ce qui nous ramène au problème de la simplicité du modèle. Prenons
l'exemple de points qui semblent distribués de façon croissante. Il s'agit des paires (1, 1), (2,
100), (3, 110), (4, 150), (5, 170) et (6, 220). Ces 6 points semblent presque alignés sur une
droite si bien qu'une simple régression linéaire (en rouge dans la figure ci-dessous) rend assez
bien compte de leur progression. Néanmoins, il est possible de régresser ces points à l'aide d'un
polynôme de degré 6 (la courbe verte), permettant une "explication parfaite" de la position des
points puisque la courbe passe sur chacun d'entre eux. Ce second modèle n'est malheureusement
pas satisfaisant car il semble expliquer autant le phénomène de croissance (qui semble essentiel)
que les fluctuations aléatoires, et il est donc à ce titre trop flexible, trop puissant ou autorisant la
prédiction d'une trop grande variance dans les données. Le pire étant que la capacité de prédiction
du modèle le plus complexe est moins bonne que celui du modèle simple. On dit que sa capacité
de généralisation est problématique. La raison est que si nous établissons une nouvelle mesure du
phénomène, le nouveau point aura plus de chance d'être proche de la ligne rouge que de la courbe
verte. C'est un peu comme si le modèle avait appris par cœur une liste d'objets sans faire
abstraction du principe qui sous-tend leur organisation. La ligne rouge par sa simplicité reflète un
processus d'abstraction. L'erreur d'un tel modèle serait par exemple de décrire parfaitement 6
oiseaux différents (un rouge, un orange, un jaune, un vert, un bleu, et un indigo) et manquer de
reconnaître un oiseau violet faute de ne pas avoir compris l'essence même d'un oiseau, par
exemple le fait de posséder des ailes. La simplification d'un modèle n'est donc pas une simple
simplification de l'esprit visant à dépasser la complexité du réel, mais bien un véritable outil de
compréhension et de conceptualisation.
9
La figure précédente a été produite avec le code suivant : %% Régression de données grâce à polyfit %Données x=[1 2 3 4 5 6] y=[1 100 110 150 170 220] %ces nombres sont inventés % Régression linéaire, c-a-d un polynôme de degré 1 de la forme ax+b p1=polyfit(x,y,1) xBis=[1:.1:6] %ce grand vecteur est utilisé pour obtenir une ligne continue yLinearPrediction=polyval(p1, xBis) % cela permet de calculer plus simplement yLinearPrediction=p1(2)+p1(1)*xBis %Régression par un polynôme de degré 6 de la forme fx6 + ex5 + dx4 + cx3 + bx2 + ax +b; cette fonction garantit que la courbe passe par tous les points p6=polyfit(x,y,6) yPolynomialPrediction=polyval(p6,xBis) %PLOT plot(xBis,yLinearPrediction,'r', x,y,'o',xBis,yPolynomialPrediction)
Le philosophe du 14e siècle Guillaume d'Ockham (ou Occam) s’est intéressé à ce principe de
simplicité, autrement appelé principe de parcimonie, que l'on traduit maintenant en langage
moderne par l'idée que les hypothèses les plus simples sont les meilleures. Nous conseillons sur
ce point précis la lecture de Roberts et Pashler (2000) ou Pitt et Myung (2002), car il est essentiel
de comprendre avant de se lancer dans le domaine de la modélisation qu'il ne s'agit pas d'une
course à la complexité, mais plutôt le contraire. Précisons que dans de nombreux domaines, la
simplicité l'emporte toujours. En cryptographie par exemple, afin d'envoyer un message secret il y
a quelques centaines d'années, une possibilité était de cadenasser un coffre, l'envoyer au
destinataire, laisser le destinataire ajouter son propre cadenas et renvoyer le coffre à l'expéditeur,
laisser l'expéditeur enlever le premier cadenas puis renvoyer le coffre au destinataire afin qu'il
puisse enfin accéder au contenu du coffre en enlevant son propre cadenas. Ce n'est pas
conceptuellement simple. Maintenant, avec l'avènement de la cryptographie informatique, certes
plus compliqué sur le plan matériel, le processus global est néanmoins plus simple : le principe de
la clé publique consiste pour le destinataire à distribuer publiquement des cadenas dont il est le
seul à détenir la clé, ce qui évite la série d'aller-retour dont nous venons de parler.
10
Pour terminer cette partie, nous précisons que la modélisation du comportement concerne des
grands champs d'études comme la psychophysique, la psychométrie, la prise de décision, les
neurosciences, tout aussi bien que des processus psychologiques fins tels que la capacité à
alterner entre deux tâches, l'inhibition mentale, etc. Le chapitre suivant exemplifie quelques uns
de ces processus afin de montrer concrètement comment on simule un modèle grâce à
l'algorithmique.
Références
Hunt, E. (2007). The mathematics of behavior. New York, NY: Cambridge University Press.
Kerr, J. (1999). Experiencing sport reversal theory. New York, NY: John Wiley & Sons.
Pitt, M. A., & Myung, I. J. (2002). When a good fit can be bad. Trends in Cognitive Sciences, 6,
421-425.
Roberts, S., & Pashler, H. (2000). How persuasive is a good fit ? A comment on theory testing.
Psychological Review, 107, 358-367.
11
Chapitre 9. Modélisation et simulation
L’explication classique de la courbe de position sérielle
La courbe de position sérielle est une caractéristique fondamentale de la mémoire que l'on
enseigne dès les premières années de la Licence en psychologie. Cette courbe illustrée dans la
figure ci-dessous montre le pourcentage de rappel, en fonction de la position de la lettre dans la
liste à retenir (la position 1 indique la première lettre de la liste). La courbe dénote un meilleur
rappel immédiat pour les lettres en début ou en fin de liste. Le rappel est immédiat dans le sens où
il intervient juste après la présentation de la liste, et non de façon différée. Dans l'exemple illustré
par la figure suivante, le rappel a été maximal (il s’agit d’une moyenne établie sur un groupe de
participants) pour la lettre B en position 1, minimal pour les lettres J et K en position 4 et 5, et
élevé pour la dernière lettre P. Les meilleurs rappels à chacune des extrémités de la liste sont
appelés respectivement l'effet de primauté et l'effet de récence.
L'explication classique repose sur deux fonctions considérées inébranlables sur le plan théorique :
la mémoire à long terme (MLT) et la mémoire à court terme (MCT). Les lettres étant présentées à
un rythme d'une lettre par seconde de façon séquentielle, les premières lettres peuvent être
répétées mentalement et bénéficier d'un meilleur encodage, tandis que les lettres subséquentes ne
peuvent pas autant bénéficier du processus de répétition mentale. Par exemple, la liste étant B-F-
H-J-K-L-P, l'auto-répétition fonctionne séquentiellement de la façon suivante : B (éventuellement
B-B-B, en mettant en boucle la répétition), puis B-F (éventuellement B-F-B-F), puis B-F-H, etc.
L’explication suppose que la lettre B étant répétée plus souvent, ses chances d'être mémorisée en
mémoire à long terme sont plus élevées que pour les lettres qui suivent. En revanche, c’est la
MCT qui est responsable du regain de mémorisation pour les lettres finales. Les dernières lettres
demeurant actives en mémoire à court terme sans effort de répétition mentale, elles peuvent
bénéficier de cette activation pour être rappelées immédiatement sans avoir été transférées en
MLT.
L’explication alternative par le phénomène d’interférence
La courbe de position sérielle est une caractéristique essentielle de la mémoire dont les modèles
doivent rendre compte. La conceptualisation de la mémoire en deux entités distinctes (MCT et
MLT) est intéressante, mais pour compléter le point de vue développé dans le chapitre précédent,
12
il semble qu’elle ne soit pas en mesure d’offrir de prédictions précises sur le plan quantitatif.
Nous développons dans ce chapitre un modèle différent qui, non seulement prédit la courbe de
position sérielle, mais également toutes sortes de déformations que la courbe peut subir en
fonction des caractéristiques de l'expérimentation. Ce modèle fondé sur le principe de
l'interférence (Brown, Neath, & Chater, 2007) a été élaboré pour expliquer, par exemple, le fait
que lorsque des lettres (e.g., H, S, N) sont suffisamment dissimilaires sur le plan phonologique
d'une liste de lettres similaires sur le plan phonologique (comme B, C, D et T), le rappel des
lettres dissimilaires semblent sortir de la courbe. On observe alors pour la courbe de rappel une
allure de dents de scie pour la liste combinant les deux ensembles (B-H-C-S-T-N). Cet effet est lié
à la moindre interférence des trois lettres dissimilaires avec les lettres restantes de la liste. Ce
résultat reflète l’intuition que les lettres sont mieux retenues car elles sortent du lot et se
retrouvent mieux isolées.
Il est donc assez aisé d’obtenir une distorsion de la nature lisse et continue de la première courbe
de position sérielle en forme de U, et qu'une simple loi fondée sur la distinction MCT/ MLT ne
suffise pas à généraliser les performances observables dans ce domaine. La solution de Brown et
collègues (héritée de la conceptualisation de Murdock datant de 1960) est que l'interférence est un
concept suffisant pour expliquer la courbe de position sérielle et ses dérivées. Cette notion
s'oppose traditionnellement au déclin de l'information supposé rendre compte à lui seul de l'oubli
en mémoire. Si vous oubliez l'endroit où vous avez garé votre véhicule, ce n'est pas
nécessairement parce que la mémoire de l'emplacement s'est effacée pendant que vous avez fait
vos courses, mais plutôt parce que l'emplacement s'est confondu avec les nombreux autres
emplacements que vous avez mémorisé dans le passé, un phénomène autrement appelé
interférence proactive. Cette forme d’interférence rend compte des effets du passé sur le futur.
L'interférence rétroactive expliquerait au contraire que le livre que vous venez de ranger sur
l'étagère A vous fait oublier par interférence l'emplacement du livre que vous avez rangé la veille
sur l'étagère B ; c’est le phénomène inverse. Lorsqu'une liste d'items est apprise pour rappel
immédiat, comme la liste B-F-H-J-K-L-P, les lettres B et P sont isolées temporellement. Elles
sont moins en concurrence avec d'autres lettres que les lettres H, J ou K. Elles sont mieux isolées
temporellement, au même titre que les lettres H, S et N du second exemple étaient isolées
phonologiquement.
La conceptualisation du modèle fondé sur un processus d’interférence utilise la notion de
discriminabilité. Nous restreignons dans cette démonstration la discriminabilité à la dimension
temporelle. Les traits phonologiques du matériel à mémoriser sont donc considérés comme
neutres. Les traits physiques sont évidemment une source supplémentaire d’interférence comme
nous l’avons vu pour l’exemple de la liste B-H-C-S-T-N. Cependant, le modèle que l’on
13
développe ici a vocation à ne pas tenir compte de la spécificité du matériel. Il faut donc
considérer que n’importe quelle lettre pourrait être associée à n’importe quelle position. Pour
autant, une première forme d’interférence opère en fonction de la simple position des items sur la
frise temporelle.
Posant que la séparation temporelle entre deux lettres i et j est
dij = xi ! x j , le modèle suit la loi
de Shepard (1987) indiquant que leur similarité est une fonction exponentielle inverse de la
distance.
!ij = e"d ij (1)
Cette fonction explique que si la distance entre i et j est nulle, leur similarité est maximale et
égale à 1. Lorsque la distance augmente entre les deux lettres, la similarité perçue décroit
rapidement mais ne devient jamais nulle. La fonction exponentielle rend compte que la similarité
perçue est environ divisée par environ 2.72 à chaque fois qu’on augmente d’une unité la distance
temporelle. Ceci correspond bien au fait que la fonction
e!x
, autrement appelée exp ou
exponentielle correspond environ à y = 2.72x. Pour vous en convaincre, vous pouvez essayer de
mettre en rapport
y = e!x
et sa voisine y = 2.72x. La figure ci-dessous reporte les valeurs de la
fonction
y = e!x
.
x
y = e!x
(ligne n)(/ligne n+1)
0 1.000 2.72
1 0.368 2.72
2 0.135 2.72
3 0.050 2.72
4 0.018 2.72
5 0.007 -
En réalité, la similarité peut décroitre parfois plus vite selon le matériel, ce qui peut-être capturé
mathématiquement par l’adjonction d’un paramètre de sensibilité c qui augmente la vitesse de
décroissance:
14
!ij = e"cdij (2)
La figure suivante représente la courbe avec c = 5.
x
y = e!5x
(ligne n)(/ligne n+1)
0 1.000 148.41
1 0.007 148.41
2 0.000 148.41
3 0.000 148.41
4 0.000 148.41
5 0.000 -
Cette fois, le rapport d’une ligne à la suivante n’est plus 2.72 mais 2.725 = 148.41.
La discriminabilité de chacun des items se calcule par rapport à l’ensemble des autres items, et
non uniquement entre ceux contigus. Par exemple, pour connaître la discriminabilité globale de B
dans la série B-F-H-J-K-L-P, on compare B avec l’ensemble F-H-J-K-L-P, pas seulement avec F.
La discriminabilité de la trace mnésique d’un item parmi un ensemble de n items est inversement
proportionnelle à la somme des similarités qu’entretien l’item avec les autres. La logique est que
plus la similarité avec les autres lettres est élevée, moins sa discriminabilité est bonne.
Di =1
!ij
j=1
j=n
" (3)
L’exemple suivant utilise 5 lettres a, b, c, d et e présentées à une seconde d’intervalle, soit à 1, 2,
3, 4, et 5 secondes. Dans la première partie du tableau EXCEL visant à calculer les distances
temporelles, nous aurions pu utiliser a, b, c, d et e en têtes de colonnes et en têtes de lignes.
Néanmoins, afin de calculer plus simplement les distances entre les lettres, nous avons remplacé
15
les lettres par la période où elles sont apparues, soit 1, 2, 3, 4, et 5 secondes. Au croisement des
colonnes et des lignes, on trouve la distance temporelle des événements. Il suffit d’écrire une
seule fois la formule au croisement de 1 et 1 : =ABS(B$1-$A2). La formule indique qu’on
calcule la valeur absolue de la différence entre la valeur de la cellule de la colonne B ligne 1 et la
valeur de la cellule de la colonne A ligne 2, soit |1-1| = 0. Il ne reste plus qu'à copier-coller la
formule à droite et en bas dans tout le reste du tableau. Puisque le symbole $ permet de conserver constant le terme qui le succède, on remarque qu’en copiant la formule vers la droite, seule la
valeur 2 est transformée en 3 : =ABS(B$1-$A3). Lorsque la formule est copiée vers le bas,
elle transforme en revanche le B en C , car la lettre n'est pas précédée par un $: =ABS(C$1-$A2). Dans les deux cas (déplacement à droite ou en bas de la formule), les $ ont maintenu constantes les valeurs 1 et A.
La deuxième partie du tableau est destinée à calculer les similarités entre items grâce à la formule
=EXP(-B2) décrite dans la première cellule, et que l’on a copiée-collée ensuite dans le reste
du tableau. La dernière ligne du tableau divise la valeur 1 par la somme des similarités par
colonne pour appliquer l’équation (3).
Distances 1 2 3 4 5 1 0 1 2 3 4
2 1 0 1 2 3
3 2 1 0 1 2
4 3 2 1 0 1
5 4 3 2 1 0
Similarités a b c d e
a 1.00 0.37 0.14 0.05 0.02
b 0.37 1.00 0.37 0.14 0.05 c 0.14 0.37 1.00 0.37 0.14 d 0.05 0.14 0.37 1.00 0.37 e 0.02 0.05 0.14 0.37 1.00
Discrimin. 0.64 0.52 0.50 0.52 0.64
Cette dernière ligne reproduit comme prédit la courbe de position sérielle en faisant la supposition
que le taux de rappel est proportionnel à la discriminabilité par lettre. Le principe de parcimonie
vu au chapitre précédent est respecté, car l’explication ne repose maintenant que sur un seul
16
processus psychologique (l’interférence) et non deux (MCT vs MLT).
Le tableau suivant illustre la puissance et la flexibilité de ce modèle. Lorsque 5 lettres sont
présentées au rythme suivant, à 1, 2, 5, 8 et 9 secondes, la troisième lettre est démarquée par une
période de 2 secondes de part et d’autre. Remarquez dans la dernière ligne comment cette
organisation temporelle (qui permet à la troisième lettre d’être isolée) se répercute sur la
discriminabilité. On remarque alors un pic de rappel pour la troisième lettre dans la nouvelle
courbe.
Distances 1 2 5 8 9
1 0 1 4 7 8
2 1 0 3 6 7
5 4 3 0 3 4
8 7 6 3 0 1
9 8 7 4 1 0
Similarités a b c d e
a 1.00 0.37 0.02 0.00 0.00
b 0.37 1.00 0.05 0.00 0.00
c 0.02 0.05 1.00 0.05 0.02
d 0.00 0.00 0.05 1.00 0.37
e 0.00 0.00 0.02 0.37 1.00
Discrimin. 0.72 0.70 0.88 0.70 0.72
Voyons comment un code MATLAB permet de passer de la modélisation à la prédiction. On
imagine par exemple que 50 participants ont été confronté à une liste de 5 lettres à apprendre au
rythme d’une lettre par seconde. Le rappel moyen observé pendant cette expérimentation montre
le pattern suivant pour l’ensemble des lettres ordonnées par position : 0.64 ; 0.52 ; 0.50 ; 0.51 ;
0.64. On souhaite trouver la valeur du paramètre c qui permette d’ajuster au mieux ces données.
17
Au vu des calculs faits précédemment, la valeur de c devrait être proche de 1, car le pattern
Discriminabilité produit dans ce cas par le modèle est très proche, et on remarque que seule la
valeur en 4e position marquée en gras donne un chiffre différent: 0.64 ; 0.52 ; 0.50 ; 0.52 ; 0.64.
Il est possible grâce à la fonction pdist de la Statistics Toolbox de calculer cette matrice, méthode
qu’il faut privilégier pour sa rigueur si vous disposez de la Statistics Toolbox. Si ce n’est pas le
cas, pour maintenir une certaine rigueur, il vaut mieux écrire quelques lignes de code pour
calculer la matrice de distance, de la façon suivante par exemple : distMatrix=[] for lettrePos=[1:5] tmp=abs([1:5]-lettrePos) distMatrix=[distMatrix;tmp] end
Ici, distMatrix est déclarée vide au départ, puis on ajoute 5 fois la valeur tmp (pour
temporaire), qui est calculée selon la valeur de lettrePos (l’ajout de tmp est fait ligne par
ligne grâce à la séparation par le point virgule). La première fois, tmp soustrait 1 à [1 :5] pour
produire les valeurs 0, 1, 2, 3, 4, puis prend la valeur absolue de ces valeurs par l’application de la
fonction abs. En l’absence de points virgules en bout de lignes de code, l’output montre tous les
résultats intermédiaires jusqu’à la fin du programme.
distMatrix =
[]
tmp =
0 1 2 3 4
distMatrix =
0 1 2 3 4
tmp =
1 0 1 2 3
distMatrix =
0 1 2 3 4
1 0 1 2 3
tmp =
2 1 0 1 2
18
distMatrix =
0 1 2 3 4
1 0 1 2 3
2 1 0 1 2
tmp =
3 2 1 0 1
distMatrix =
0 1 2 3 4
1 0 1 2 3
2 1 0 1 2
3 2 1 0 1
tmp =
4 3 2 1 0
distMatrix =
0 1 2 3 4
1 0 1 2 3
2 1 0 1 2
3 2 1 0 1
4 3 2 1 0
>>
Une fois la matrice des distances construite, le programme pose une valeur absurde pour le
meilleur ajustement bestFit=1000000. Cette valeur arbitraire est élevée pour être certain
qu’au moins une valeur de c conduira à un meilleur ajustement. Forcément, cela se produit lors de
la première passe dans la boucle pour c = 1.
Observons ce qui est calculé dans la boucle for c=1:5 simMatrix=exp(-c*distMatrix) D=1./sum(simMatrix) fit=sum(abs(D-data)) (...) end
- On y retrouve l’équation (2) ici : simMatrix=exp(-c*distMatrix); - On retrouve l’équation (3) ici : D=1./sum(simMatrix);
19
- Enfin, l’ajustement est calculé par fit=sum(abs(D-data)); On commence par le calcul de la différence entre le pattern prédit D et data. La valeur absolue
abs a pour objectif d’éviter que des erreurs positives et négatives s’annulent. Par exemple, si le
pattern prédit est .5 ; .5 ; .5 ; .5 et que les données sont 0 ;1 ;0 ;1, la différence de pattern serait
égale à zéro. En prenant la valeur absolue, on trouve bien des erreurs de .5 pour chaque position
et une somme d’erreur globale égale à 4 ! .5 = 2. Nous verrons dans le chapitre suivant que
prendre que sommer les valeurs absolues des erreurs n’est pas une méthode satisfaisante. Nous
développerons d’autres méthodes utilisant les carrés des erreurs et la notion de vraisemblance
dans le chapitre suivant.
La boucle intègre un test pour savoir si l'ajustement trouvé est optimal : for c=1:5 simMatrix=exp(-c*distMatrix) D=1./sum(simMatrix) fit=sum(abs(D-data)) if fit< bestFit disp('meilleur ajustement trouvé') bestFit=fit bestc=c end end
On teste ensuite si fit < bestFit . Lorsque c’est le cas, il faut enregistrer que le meilleur
ajustement (qu'on appelle bestFit) est maintenant trouvé. C’est grossièrement le même principe
qui sert le divertissement télévisé « The Best », où le compétiteur jugé meilleur que le précédent
prend sa place, avant d’être éventuellement remplacé par un autre, mieux jugé. Tant qu’un
meilleur ajustement n’est pas trouvé, on ne change pas la valeur c qui a été trouvée comme
donnant le pattern prédit le plus proche des données. Cette valeur, pour ne pas être confondue
avec c est appelée bestc.
Une fois la recherche de bestc terminée, il faut reprendre l’équation (2) en prenant soin
d’utiliser bestc au lieu d’un quelconque c. On trace ensuite le pattern prédit et celui observé
grâce à la fonction plot qui accepte autant de couples x/y que l’on souhaite. Ici, on indique donc
une série de x, suivie des y correspondant, puis une autre série de x, suivie d’autres y. Il s’agit
respectivement des positions des lettres, du pattern prédit, de la position des lettres (à nouveau) et
du pattern observé. Les chaînes de caractères qui suivent chacun des couples x/y permettent de
choisir l’allure des courbres : '--bo' pour discontinu + bleu + marqueur rond, et '-rx' pour
continu + rouge + marqueur x.
Sachant que nous avons fait varier un paramètre du modèle afin de s’approcher au mieux des
données, on peut parler de simulation. Le chapitre suivant développera plus en détail cet aspect.
Code %% Modèle de Brown, Neath and Chater, 2007 %% Mini simulation %Efface clear all, clc % données data=[0.64 0.52 0.50 0.51 0.64]; % Timing choisi lors de l’expérimentation timing=[1:5];
20
% distances distMatrix=nan(5,5) %pdist(timing) %La statistics toolbox est requise pour cette fonction; sinon, utiliser ceci : distMatrix=[0 1 2 3 4 1 0 1 2 3 2 1 0 1 2 3 2 1 0 1 4 3 2 1 0] %entré à la main %Test du modèle bestFit=1000000;%valeur absurde, élevée for c=1:5 simMatrix=exp(-c*distMatrix) D=1./sum(simMatrix) fit=sum(abs(D-data)) if fit< bestFit disp('a better fit has been found') bestFit=fit bestc=c end end %résultat disp('RESULT **********') bestD=1./sum(exp(bestc*(-distMatrix))) bestc %Figure plot(timing,bestD,'--bo', timing,data,'-rx') legend('Model','Data',4)
Output
distMatrix =
NaN NaN NaN NaN NaN ((on réserve ici un espace pour la matrice ; on remplit
NaN NaN NaN NaN NaN l’espace de non-chiffres ; NaN signifie Not a Number))
NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN
NaN NaN NaN NaN NaN
distMatrix =
0 1 2 3 4 ((on remplace les NaN par des chiffres))
1 0 1 2 3
2 1 0 1 2
3 2 1 0 1
4 3 2 1 0
c = ((on écrit c pour savoir où la boucle en est))
1
21
simMatrix =
1.0000 0.3679 0.1353 0.0498 0.0183 ((matrice des similarités calculée avec c = 1))
0.3679 1.0000 0.3679 0.1353 0.0498
0.1353 0.3679 1.0000 0.3679 0.1353
0.0498 0.1353 0.3679 1.0000 0.3679
0.0183 0.0498 0.1353 0.3679 1.0000
D =
0.6364 0.5206 0.4984 0.5206 0.6364 ((Discriminabilité par position))
fit =
0.0200
a better fit has been found ((car fit est inférieur à 1000000))
bestFit = ((bestFit=1000000 est remplacé par bestFit = 0.0200 ; c’est le nouveau
score à battre))
0.0200
bestc = ((on retient que la meilleure valeur de c est pour l’instant égale à 1 ; cela peut
changer))
1
c = ((la boucle entreprend un deuxième passage avec la nouvelle valeur c = 2))
2
simMatrix =
1.0000 0.1353 0.0183 0.0025 0.0003
0.1353 1.0000 0.1353 0.0183 0.0025
0.0183 0.1353 1.0000 0.1353 0.0183
0.0025 0.0183 0.1353 1.0000 0.1353
0.0003 0.0025 0.0183 0.1353 1.0000
D =
0.8647 0.7743 0.7649 0.7743 0.8647
22
fit =
1.2330 ((ce fit n’est pas inférieur à 0.0200 ; il est normal qu’on ne voie pas le message a
« a better fit has been found »))
c = ((la boucle prend la troisième valeur))
3
simMatrix =
1.0000 0.0498 0.0025 0.0001 0.0000
0.0498 1.0000 0.0498 0.0025 0.0001
0.0025 0.0498 1.0000 0.0498 0.0025
0.0001 0.0025 0.0498 1.0000 0.0498
0.0000 0.0001 0.0025 0.0498 1.0000
D =
0.9502 0.9073 0.9054 0.9073 0.9502
fit =
1.8104 ((ce fit n’est pas inférieur à 0.0200 ))
c =
4
simMatrix =
1.0000 0.0183 0.0003 0.0000 0.0000
0.0183 1.0000 0.0183 0.0003 0.0000
0.0003 0.0183 1.0000 0.0183 0.0003
0.0000 0.0003 0.0183 1.0000 0.0183
0.0000 0.0000 0.0003 0.0183 1.0000
D =
0.9817 0.9643 0.9640 0.9643 0.9817
23
fit =
2.0461
c =
5
simMatrix =
1.0000 0.0067 0.0000 0.0000 0.0000
0.0067 1.0000 0.0067 0.0000 0.0000
0.0000 0.0067 1.0000 0.0067 0.0000
0.0000 0.0000 0.0067 1.0000 0.0067
0.0000 0.0000 0.0000 0.0067 1.0000
D =
0.9933 0.9867 0.9866 0.9867 0.9933
fit =
2.1365
RESULT **********
bestD = ((on récapitule ici les valeurs qui ont été trouvées comme étant les plus proches
des données))
0.6364 0.5206 0.4984 0.5206 0.6364
bestc =
1
>> ((le programme est terminé et attend la main ; dans une autre fenêtre, la figure
est tracée))
24
1 1.5 2 2.5 3 3.5 4 4.5 50.48
0.5
0.52
0.54
0.56
0.58
0.6
0.62
0.64
0.66
Model
Data
Références
Brown, G. D. A., Neath, I., & Chater, N. (2007). A temporal ratio model of memory.
Psychological Review , 114 , 539-576.
Murdock, B. B. (1960). The distinctiveness of stimuli. Psychological Review, 67 , 16- 31.
Shepard, R. N. (1987). Toward a universal law of generalization for psychological science.
Science, 237, 1317-1323.
25
Chapitre 10. L'ajustement du modèle aux données
Catégorisation, avec calculs EXCEL
Afin d'expliquer comment on calcule l'ajustement d'un modèle aux données, nous développons un
modèle de la catégorisation. La catégorisation perceptive est un processus consistant à regrouper
des objets dans des ensembles. C'est un processus à la base de la conceptualisation (e.g.,
distinguer des objets vivants d'objets non vivants) et de la reconnaissance (e.g., d’objets, de
visages, etc.). Ici, nous évoquerons plutôt la catégorisation artificielle qui demande au participant
de classer des objets selon une règle pré-définie. C'est un processus à la base de la
conceptualisation (e.g., reconnaître des objets vivants d'objets non vivants), à la reconnaissance Il
suffit d’une légère adaptation des équations présentées dans le chapitre précédent pour généraliser
le calcul des distances temporelles aux distances physiques. Dans ce domaine permettant de
rendre compte de la mémorisation d’objets multidimensionnels, on présente le modèle à
exemplaire développé par Nosofsky (1984, 1986). On utilise ici un paradigme permettant de
tester la facilité à grouper/classer des exemplaires dans une catégorie par opposition à une autre
catégorie, en fonction de l’homogénéité des catégories.
Selon ce modèle, les stimuli visualisés laissent des traces mnésiques appelées exemplaires, par un
processus inconscient. Plus un exemplaire est similaire aux membres de sa catégorie, plus il est
probable qu’il soit associé à cette catégorie par l’apprenant. Le modèle à exemplaires est appelé
modèle à contexte, du fait que l’ensemble des stimuli forme un contexte qui détermine le
processus de classification. Dans ce modèle, la distance entre deux stimuli i et j est calculée par la
métrique de Minkowski
dij = xia ! x ja
r
a=1
a=n
"#
$ %
&
' (
1/ r
pour laquelle on pose r = 1 lorsque qu’on compte simplement un nombre de différences entre
deux objets. On utilise sinon r = 2 pour calculer la distance euclidienne, qui est celle mesurée plus
classiquement entre deux points avec une règle graduée par exemple ; dans ce cas, ce n’est ni plus
ni moins que le théorème de Pythagore déguisé qui s’applique (pour rappel, l'exposant ! équivaut
à appliquer une racine carrée).
Commençons donc par dire que l’équation que nous allons utiliser se simplifie rapidement avec r
= 1 de la façon suivante :
dij = xia ! x ja
a=1
a=n
" (1)
Pour prendre un exemple, observons l’ensemble d’objets suivants répartis dans un diagramme (en
l'occurrence, undiagramme de Hasse) qui permet une organisation selon une logique de similarité.
Dans ce schéma, on peut calculer les différences (en termes de distance) entre le carré blanc, le
carré noir, le triangle blanc et le triangle noir. Lorsqu’on compte le nombre de traits (e.g., couleur,
forme) différents entre les objets, on pose r = 1. Ce type de distance fondée sur r = 1 est appelée
city-block. Elle représente l'idée que pour mesurer la distance entre les objets, on procède comme
si on parcourait les rues orthogonales d'une ville. Une arête parcourue entre deux objets
correspond à une différence, donc, à une distance égale à 1; lorsqu’on doit parcourir deux arêtes
pour rejoindre deux objets, ces objets présentent deux différences (distance = 2). Pour calculer le
nombre de différences entres deux objets i et j, il suffit donc de compter les différences pour
chacune des dimensions. Dans l’exemple, les objets sont construits sur la base de n = 2
dimensions. Le signe somme (") est indexé sur ces dimensions et prend la valeur a = 1 pour la
26
dimension couleur et la valeur a = 2 pour la dimension forme. Par exemple, entre le carré blanc et
le triangle noir, pour la dimension couleur (a = 1), les valeurs |xi1 ! xj1| = 1 puisque les traits
présentent une différence ; c’est en quelque sorte comme si on écrivait blanc – noir = 1. Pour la
seconde dimension, le raisonnement est identique et |xi2 ! xj2| = 1. Lorsqu’on somme ce nombre
de différences de traits, on obtient bien 2 de la manière suivante :
On retrouve le nombre de différences pour chacune des paires dans la matrice suivante (dans
laquelle nous avons grisé les diagonales pour faire ressortir les régularités):
Pour calculer le nombre de différences entres deux objets i et j, il suffit donc de compter leur
différence pour chacune des dimensions. Dans l’exemple, il y a n = 2 dimensions. Le signe
somme est indexé sur ces dimensions et prend la valeur a = 1 pour la dimension couleur et la
valeur a = 2 pour la dimensions forme. Par exemple, entre le carré blanc et le triangle noir, pour
la dimension couleur (a = 1), les valeurs |xi1 ! xj1| = 1 puisque les traits présentent une différence ;
c’est un peu comme si on écrivait blanc – noir = 1. Pour la seconde dimension, le raisonnement
est identique et |xi2 ! xj2| = 1. Lorsqu’on somme ce nombre de différence de traits, on obtient bien
2 de la manière suivante :
27
dij = xia ! x ja
a=1
a=2
" = xi1 ! x j1 + xi2 ! x j2 =1+1 = 2
La matrice des distances est donc la suivante après avoir appliqué la formule à toutes les paires
d’objets :
Carré blanc Carré noir Triangle blanc Triangle noir
0 1 1 2
1 0 2 1
1 2 0 1
2 1 1 0
La similarité ! entre deux stimuli i et j est la fonction exponentiellement décroissante décrite dans
le chapitre précédent :
!ij = e"cdij (2)
En supposant que c = 1, nous obtenons la matrice de similarités suivante :
1,00 0,37 0,37 0,14
0,37 1,00 0,14 0,37
0,37 0,14 1,00 0,37
0,14 0,37 0,37 1,00
Il s'agit maintenant d’assigner arbitrairement des catégories à ces quatre objets. On suppose par
exemple que seul le triangle noir appartient à la seconde catégorie nommée Y ; les trois autres
objets appartiennent à la catégorie X. La formule suivante suppose qu’on doit calculer la
similarité d’un stimulus s aux exemplaires x et y des catégories X et Y. Par exemple, pour
connaître la probabilité de classer le carré blanc dans la catégorie X, on somme sa similarité à tous
les objets de X (y compris lui-même), et on divise par la somme de ses similarités à X additionnée
à la somme de ses similarités à Y. Cette formule qui donne la probabilité de classer le stimulus s
dans la catégorie X est la règle de choix de Luce (Luce, 1963) :
p(X /s) =
!sx
x"X
#
!sx
x"X
# + !sy
y"Y
# (3)
L'ensemble des trois équations forment le modèle appelé General Context Model (GCM ), qui
peut être agrémenté de nombreux autres paramètres (le paramètre de sensibilité général, le
paramètre d’attention aux dimensions, la fréquence des exemplaires, le paramètre ! permettant
d’associer au départ de l’apprentissage des réponses aléatoires pour terminer par des réponses de
plus en plus déterminées de type 0/1). Ici, on se contentera de voir comment fonctionne le modèle
simplifié.
28
Pour calculer la probabilité de classer le carré blanc dans la catégorie X, on utilise la similarité
qu’entretient le carré blanc avec chacun des objets de X, notée en gras dans la ligne ci-dessous
empreinte au tableau vu précédemment.
1.00 0.37 0.37 0.14
Au contraire, la similarité du carré blanc au triangle noir de la catégorie Y se résume à la valeur en
gras ci-dessous :
1.00 0.37 0.37 0.14
L’application de la formule donne alors :
p(X /s) =(1+ 0.37 + 0.37)
(1+ 0.37 + 0.37) + (0.14)=
(1.74)
(1.74) + (0.14)0.93
Le même calcul appliqué au carré noir donne 0.80. Idem pour le triangle blanc. Le calcul pour le
triangle noir donne 0.47. Sur le plan psychologique, cela signifie que le carré noir, en raison de sa
nature prototypique de la catégorie X, a une chance élevée d’être classé dans cette catégorie. Les
deux autres membres de la catégorie, en étant plus proche du triangle noir, ont moins de chance
d’être classés en X. En conséquence du fait que le triangle noir n’appartienne pas à une catégorie
fréquente et qu’il présente une proximité avec la catégorie X, sa probabilité d’être catégorisé
comme Y (équivalent à 1 – 0.47 = .53) n’est pas élevée.
Calcul MATLAB
Nous allons prendre ici l’exemple d’une tâche de catégorisation pendant laquelle les participants
doivent trier chacun des objets (dans deux boîtes par exemple, X et Y) sans aucune indication de
règle de tri au départ. Seul un feedback qui succède directement au tri d'un objet leur permet
d’apprendre progressivement la règle sous-jacente qui a été choisie au départ par
l'expérimentateur. On a présenté 5 fois de suite 4 objets (un carré blanc, un carré noir, un triangle
blanc et un triangle noir). Dans ce cas, on dit que les participants ont été confrontés à 5 blocs
d’apprentissage. Parfois, on regroupe les blocs en époques. Par exemple, si le participant est
confronté à 40 objets, il a subit 2 époques d’apprentissage composées de 5 blocks chacune. Dans
chaque bloc, les objets sont permutés au hasard, souvent avec la seule contrainte que le dernier
objet d’un bloc et le premier objet du bloc suivant ne soient pas les mêmes. L’ordre
d’apprentissage pourrait être le suivant pour un participant :
carré blanc, carré noir, triangle noir, triangle blanc,
carré noir, triangle noir, carré blanc, triangle blanc,
triangle noir, carré blanc, triangle blanc, carré noir,
triangle blanc, carré blanc, carré noir, triangle noir.
L’ordre étant aléatoire, il est probablement différent d’un participant à l’autre.
La tâche du sujet consiste à choisir la catégorie (X ou Y) de chaque objet. Une fois son choix
effectué, on indique au sujet si sa réponse est correcte ou non. Il s’agit d’un apprentissage
supervisé. Par essai-erreur, on attend du participant qu’il découvre progressivement les catégories
choisies au départ par l’expérimentateur, soit :
carré blanc = X ; carré noir = X ; triangle blanc = X ; triangle noir = Y.
La tâche étant plus complexe qu’il n’y paraît, on imagine que le participant a classé 4 fois sur 5 le
carré blanc comme appartenant aux X ; 3 fois sur 5 le carré noir comme X ; 3 fois sur 5 le triangle
29
blanc comme X ; 1 fois sur 5 le triangle noir comme X. Si les 4 objets sont numérotés de 1 à 4, on
peut écrire la proportion de classification dans la catégorie X :
data = [0.80 0.60 0.60 0.20],
simplement en divisant pour chaque objet le nombre de fois qu’il a été classé en X, divisé par le
nombre de présentations (par exemple 4/5 = .80).
Le pattern prédit par les calculs EXCEL précédents est [0.93 0.80 0.80 0.47]. Pour notre
programme MATLAB, on décide d’appeler ce pattern p_Xcat, signifiant "probabilité de choisir
la catégorie X". Un principe de base de l'algorithmique est que le nom des variables doit être
limpide, mais pas trop long. Il est donc déconseillé de nommer la variable
"prob_de_choisir_la_cat X ".
Le programme calcule de façon automatisée p_Xcat. Comme dans le chapitre précédent, on
commence par calculer simMatrix=exp(-c*distMatrix). En revanche, un point plus compliqué
consiste à trouver une méthode afin que le programme additionne uniquement les similarités des
objets d'une catégorie donnée. C'est un point un peu délicat ici. En utilisant EXCEL, nous avions
mis en gras les probabilités à additionner. Cette information visuelle doit être codée maintenant
pour MATLAB. Pour ce faire, on indique au programme ces cellules par la matrice : Xcat = ... [1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0]
Au contraire des calculs faits auparavant avec Excel, on souhaite additionner en colonne plutôt
qu'en ligne, et c'est la raison pour laquelle on code en ligne comme suit :
1
1
1
0
plutôt qu'en colonne : 1 1 1 0. Xcat indique par la valeur 1 les objets (toujours numérotés de 1 à 4) qui appartiennent à la
catégorie X dans la matrice de similarités. A partir de Xcat, on peut alors indiquer facilement
quels objets appartiennent à la catégorie Y. C'est simplement l'inverse, calculé ainsi : Ycat=abs(Xcat-1)
Cela donne le résultat suivant :
Ycat =
0 0 0 0
0 0 0 0
0 0 0 0
1 1 1 1
Pour calculer
!sx
x"X
# et
!sy
y"Y
# on utilise :
eta_Xcat=sum(simMatrix.*Xcat) eta_Ycat=sum(simMatrix.*Ycat)
Par exemple, si on copie une partie de la formule dans la fenêtre de calcul de MATLAB, on
30
obtient :
>> simMatrix.*Xcat
ans =
1.0000 0.3679 0.3679 0.1353
0.3679 1.0000 0.1353 0.3679
0.3679 0.1353 1.0000 0.3679
0 0 0 0
La première COLONNE correspond bien à notre calcul précédent qui avait consisté à ne sommer
que les parties en gras. Ici, le 0.14 que nous avions dans EXCEL et qui n'était pas pris en compte
(de façon implicite) s'est simplement transformé pour être explicite en 0. Pour rappel, nous avions
dans EXCEL :
1.00 0.37 0.37 0.14
Il n'y a plus qu'à sommer les COLONNES pour obtenir les
!sx
x"X
# .
La fonction sum procède par défaut en faisant les sommes des colonnes :
>> sum(simMatrix.*Xcat)
ans =
1.7358 1.5032 1.5032 0.8711
Les mêmes calculs pour Y donnent :
>> simMatrix.*Ycat
ans =
0 0 0 0
0 0 0 0
0 0 0 0
0.1353 0.3679 0.3679 1.0000
et
>> sum(simMatrix.*Ycat)
ans =
0.1353 0.3679 0.3679 1.0000
Pour le carré noir, le premier objet (on se focalise donc sur la première colonne), on retrouve
bien, si on arrondit les valeurs 1.7358 et 0.1353, les valeurs obtenues par le calcul précédent avec
EXCEL, soit 1.74 et 0.14.
31
Dans le programme, nous avons nommé les variables ainsi :
eta_Xcat, valant donc [1.7358 1.5032 1.5032 0.8711] au terme des calculs, et
eta_Ycat, valant donc [0.1353 0.3679 0.3679 1.0000] au terme des calculs.
On souhaite donc pour chaque objet calculer eta_Xcat/(eta_Xcat+ eta_Ycat). Pour la première
valeur par exemple, on obtiendrait 1.7358/(1.7358 + 0.1353) = 0.9277, correspondant bien à
notre valeur EXCEL 0.93. MATLAB permet de faire les calculs pour les 4 objets en même temps
si on utilise l'opérateur "./" au lieu de "/", lui indiquant qu'il doit faire le calcul pour chaque
nombre des matrices, par colonne (sinon, il fait un calcul matriciel plus complexe). On obtient
alors :
>> p_Xcat=eta_Xcat./(eta_Xcat+eta_Ycat)
p_Xcat =
0.9277 0.8034 0.8034 0.4656
Récapitulons le programme entier et ce qu'il permet d'afficher en output :
%% Modèle de Nosofsky, 1986 %% Mini Modèle, mini simulation %Clear clear all, clc % Les objets suivants sont numérotés de 1 à 4 % Carré blanc % Carré noir % Triangle blanc % Triangle noir % données data=[0.80 0.60 0.60 0.20] % distances distMatrix=nan(5,5); distMatrix = ... [0 1 1 2 %entrée à la main 1 0 2 1 1 2 0 1 2 1 1 0] % catégories : X, X, X, Y ; organisées en lignes dans la matrice suivante Xcat = ... [1 1 1 1 %by hand 1 1 1 1 1 1 1 1 0 0 0 0] %Mini exemplar model c =1 simMatrix=exp(c*(-distMatrix)) eta_Xcat=sum(simMatrix.*Xcat) eta_Ycat=sum(simMatrix.*Ycat) p_Xcat=eta_Xcat./(eta_Xcat+eta_Ycat)
32
Output
data =
0.8000 0.6000 0.6000 0.2000
distMatrix =
0 1 1 2
1 0 2 1
1 2 0 1
2 1 1 0
Xcat =
1 1 1 1
1 1 1 1
1 1 1 1
0 0 0 0
Ycat =
0 0 0 0
0 0 0 0
0 0 0 0
1 1 1 1
c =
1
simMatrix =
1.0000 0.3679 0.3679 0.1353
0.3679 1.0000 0.1353 0.3679
0.3679 0.1353 1.0000 0.3679
0.1353 0.3679 0.3679 1.0000
eta_Xcat =
1.7358 1.5032 1.5032 0.8711
eta_Ycat =
33
0.1353 0.3679 0.3679 1.0000
p_Xcat =
0.9277 0.8034 0.8034 0.4656
>>
Fonctions d'ajustement (RMSE et vraisemblance)
Nous abordons maintenant un point essentiel de la simulation informatique. La simulation d’un
modèle a pour vocation de connaître la qualité de la prédiction, au regard de données disponibles.
Nous allons compliquer le programme précédent en comparant le modèle à exemplaire à un
modèle concurrent, et estimer leur ajustement respectif aux données. Le modèle concurrent choisi
est fondé sur le hasard. Et si le hasard prédisait mieux les données que le modèle à exemplaire ?
Si un participant répond au hasard, il choisit une fois sur deux en moyenne la catégorie X, et la
probabilité prédite pour les 4 objets devrait être de 0.5 à chaque fois:
p_Xcat =
0.5 0.5 0.5 0.5
L'objectif est d'estimer lequel des deux patterns prédits (i.e., p_Xcat_MODEL = [0.9277 0.8034
0.8034 0.4656]
ou p_Xcat_GUESS = [0.5 0.5 0.5 0.5]) est le plus proche des données data = [0.80 0.60 0.60
0.20]. Les différences entre les valeurs prédites et celles observées se nommant les résidus, nous
présentons trois méthodes, ordonnées de façon croissante pour leur qualité : la valeur absolue
moyenne des résidus, le carré moyen des résidus, et la vraisemblance.
La valeur absolue moyenne est simplement calculée de la façon suivante :
>> mean(abs(p_Xcat_MODEL-data))
ans =
0.2000
Puisque :
>> p_Xcat_MODEL-data
ans =
0.1277 0.2034 0.2034 0.2656
De la même façon, on obtient :
>> mean(abs(p_Xcat_GUESS-data))
ans =
0.2000
Puisque :
>> p_Xcat_GUESS-data
34
ans =
-0.3000 -0.1000 -0.1000 0.3000
Selon cette méthode, les deux modèles (celui à exemplaires, et celui fondé sur le hasard) ajustent
aussi bien l'un que l'autre le pattern de données. Cependant, cette méthode est insatisfaisante sur
deux points. Le calcul des carrés des résidus semble mieux convenir à une multitude de formules
statistiques que le calcul des valeurs absolues et, deuxième point, la valeur absolue met moins en
évidence la gravité des erreurs de prédiction que le carré des erreurs. En prenant des chiffres plus
simples tels que des résidus de 1 et 3 pour un premier modèle et 2 et 2 pour un second modèle, on
remarque que le résidu moyen pour les deux modèles est 2, car (1 + 3)/2 = 2 et (2 + 2)/2 = 2;
cependant, le premier modèle a conduit à une erreur élevée une fois (3), en comparaison du
second modèle dont les erreurs restent raisonnables. Dans ce cas, mettre les résidus au carré
capturent bien l'idée que plus les résidus sont élevés, plus l'erreur est grave : (12 + 3
2) = 10 et (2
2
+ 22) = 8. Afin de prendre le carré moyen, on calcule la racine carrée de la somme finale pour
obtenir racine(10) = 3.2et racine(8) = 2.8. Sous MATLAB, l'écriture est la suivante :
>> sqrt(mean((p_Xcat_MODEL-data).^2))
ans =
0.2059
>>
et
>> sqrt(mean((p_Xcat_GUESS-data).^2))
ans =
0.2236
Ce carré moyen de l'erreur, calculé grâce à la racine carrée finale porte le terme technique en
anglais de RMSE (Root Mean Square Error). En calculant le carré moyen des résidus pour notre
exemple, on observe que le second modèle est plus satisfaisant. Notez au passage que
sqrt(mean((p_Xcat_MODEL-data).^2)) est bien différent de sqrt(mean(p_Xcat_MODEL-
data).^2), car dans ce dernier cas, on calcule la moyenne de (p_Xcat_MODEL-data), avant de
mettre le résultat au carré, pour finir par calculer la racine carrée, ce qui revient à calculer
abs(mean(p_Xcat_MODEL-data)). La formule correcte sqrt(mean((p_Xcat_MODEL-data).^2))
met au contraire chacune des valeurs du vecteur des différences au carré avant de les moyenner.
Par exemple, ici :
>> (p_Xcat_MODEL-data)
ans =
0.1277 0.2034 0.2034 0.2656
35
>> (p_Xcat_MODEL-data).^2
ans =
0.0163 0.0414 0.0414 0.0705
>> mean((p_Xcat_MODEL-data).^2)
ans =
0.0424
>> sqrt(mean((p_Xcat_MODEL-data).^2))
ans =
0.2059
>>
Certaines formules utilisent simplement la somme des résidus au carré, qu'on retrouve en anglais
sous le terme de Residual Sum of Squares ou RSS. Cette méthode permet de calculer le
pourcentage de variance expliqué par la formule R2 = 1 - RSS/TSS. Si les données sont [1 2], et
que le modèle prédit [3 4], les erreurs sont [2 2], et le carré des erreurs est [4 4] (ce qui somme à
8), pour une variance totale égale à (1 - 1.5) 2
+ (2 - 1.5) 2
= 0.5. La totalité de la variance est TSS
(Total Sum of Squares). Etant donné que la totalité de la variance dans les données peut se
décomposer entre une partie expliquée et une partie non expliquée correspondant aux résidus, on
peut écrire :
Variance Totale = Variance Expliquée + Résidus, ou
Variance Expliquée = Variance Totale - Résidus, ou
Variance Expliquée = (Variance Totale - Résidus) / Variance Totale, ou
Variance Expliquée = 1 - Résidus / Variance Totale.
Si on applique cette formule avec l'exemple précédent, on trouve :
Variance Expliquée = 1 – Résidus / Variance Totale = 1 -8/0.5 = -15, ce qui est un résultat
aberrant. La raison est que le modèle doit au moins prédire les données moyennes, ce qui n'est pas
le cas ici puisque les données moyennes tournent autour de 1.5 alors que ce que produit le modèle
tourne autour de 3.5. Par exemple, si les données sont [1 2], et que le modèle prédit [0 3], la
moyenne des données égale la moyenne du modèle, c'est-à-dire 1.5. Les erreurs sont [-1 1] pour
une variance totale toujours égale à 0.5, et le carré des erreurs est [1 1] (ce qui somme à 2). Dans
ce cas, Variance Expliquée = 1 -2/0.5 = -3, ce qui donne à nouveau un résultat aberrant.
En fait, une dernière contrainte exige que le modèle offre une variance moins élevée que les
données. Par exemple, si les données sont [0 3], et que le modèle prédit [1 2], la moyenne des
données égale la moyenne du modèle, c'est-à-dire 1.5. Les erreurs sont [1 -1] pour une variance
totale identique, maintenant égale à (0 - 1.5) 2
+ (3 - 1.5) 2
= 4.5. Cette fois, Variance Expliquée =
1 -2/4.5 = .56, soit 56% de variance expliquée. Si l'erreur était quasi nulle pour un autre modèle,
on voit bien ici que 1 -0/4.5 = 1, soit 100% de variance expliquée.
La méthode précédente fonctionne très bien pour la régression linéaire par exemple, car les
contraintes que nous venons d'évoquer sont d'emblée respectées. Ce n'est en revanche pas le cas
pour le modèle pris en exemple ici, car ce modèle peut prédire des patterns dans l'ensemble plus
36
élevés que celui observé (dans ce cas, les moyennes des patterns prédits et observés ne peuvent
pas être égales).
Une troisième solution que nous conseillons à l'instar de nombreux collègues est le calcul de la
vraisemblance du modèle, qui se fait parfois sur la base de la distribution binomiale (Lamberts,
1997). La vraisemblance du modèle tient compte de la gravité des erreurs, en utilisant une
distribution normale (i.e., gaussienne) des erreurs. L'adéquation du modèle sera jugée de plus en
plus improbable à mesure que l'erreur sera importante. Par exemple, si un modèle prévoit que la
réponse est donnée au hasard, on pose p = .5. La distribution binomiale indique par exemple pour
n = 5 réponses données, la probabilité d'obtenir k réponses "Catégorie X". Pour k = 0, 1, 2, 3, 4, 5,
ces probabilités sont respectivement : 0.03, 0.16, 0.16, 0.31, 0.31, 0.03, des valeurs qui
approximent la courbe normale à mesure que n augmente. La probabilité de donner 5 réponses du
même type par le hasard est seulement de 3%. Sous MATLAB, on calcule la probabilité comme
suit :
>> binopdf(5,5,.5)
ans =
0.0312
Cette probabilité correspond à la probabilité d'observer un certain nombre de réponse "Catégorie
X" étant donné le nombre de réponses "Catégorie X" observées. Probabilité et vraisemblance sont
identiques pour la loi binomiale.
Lorsque des événements sont indépendants, leurs probabilités se multiplient. Par exemple, étant
donné que la probabilité de naissance d'un garçon est environ .5, la probabilité pour que deux
femmes aient 5 garçons chacune est .03 ! .03 = 0.0009, soit moins d'une chance sur 1000.
Puisque multiplier des petites valeurs n'est pas pratique (on finit par avoir des exposants négatifs
illisibles), on calcule donc de préférence le logarithme de la vraisemblance (afin d'additionner les
valeurs plutôt que de les multiplier; ce n'est qu'une astuce mathématique sans rapport avec le
concept de vraisemblance). On remarque que Log(0.03) + Log(0.03) = -3.5066 -3.5066 = -7.013,
de la même manière que log(0.0009) = -7.013.
Pour notre exemple, la vraisemblance pour le modèle se calcule de la façon suivante pour le
premier objet :
>> binopdf(0.80*5,5, 0.9277)
ans =
0.2678
Pour le second modèle, fondé sur le hasard, on trouve :
>> binopdf(0.80*5,5, 0.5)
ans =
0.1562
Pour appliquer la formule aux 4 objets, on utilise pour le premier modèle :
>> binopdf(data*5,5, p_Xcat_MODEL)
37
ans =
0.2678 0.2004 0.2004 0.1899
Pour le second modèle :
>> binopdf(data*5,5, p_Xcat_GUESS)
ans =
0.1562 0.3125 0.3125 0.1562
Pour calculer la somme des logarithmes, on utilisera plutôt :
>> sum(log(binopdf(data*5,5, p_Xcat_MODEL)))
ans =
-6.1937
et :
>> sum(log(binopdf(data*5,5, p_Xcat_GUESS)))
ans =
-6.0389
La vraisemblance s'avère supérieure pour le modèle stipulant que le participant répond au hasard
puisque -6.0389 est une valeur supérieure à -6.1937, un résultat qui contredit celui obtenu en
calculant le RMSE. Nous avons donc bien démontré à l'aide de cet unique exemple que la
fonction d'ajustement calculé par les simples valeur absolues des erreurs de prédiction, les carrés
des erreurs de prédiction, et la vraisemblance conduisent à des résultats contradictoires. Pour cette
raison, il est donc préférable d'utiliser la méthode la plus satisfaisante conceptuellement (i.e., la
vraisemblance du modèle).
Le programme complet est le suivant :
%% Model of Nosofsky, 1986 % Mini model (including the sensitivity parameter c), mini simulation (including measures of fit), including a comparison with a model based % on a participant guessing responses %Clear clear all, clc %The following objects are numbered from 1 to 4 % Carre blanc % Carre noir % Triangle blanc % Triangle noir % Categories for the respective objects: X, X, X, Y, represented by % categories=[0 0 0 1]; %categories=[0 0 0 1]; % can be specified otherwise %CONSTANT
38
nBLOCKS=5; nOBJECTS=4; % data; mean probability of choosing the X category after 5 blocks, for 2 % different subjects data=[0.80 0.60 0.60 0.20] % distances distMatrix=nan(5,5); distMatrix = ... [0 1 1 2 %by hand 1 0 2 1 1 2 0 1 2 1 1 0] %categories, given by row Xcat = ... [1 1 1 1 %by hand 1 1 1 1 1 1 1 1 0 0 0 0] Ycat=abs(Xcat-1) %Test of the exemplar model, in comparison to guessing bestLogLikelihood=-1000000;%fake value for c=[1 5] % The program could explore other values of c here %Prediction simMatrix=exp(c*(-distMatrix)) eta_Xcat=sum(simMatrix.*Xcat) eta_Ycat=sum(simMatrix.*Ycat) p_Xcat=eta_Xcat./(eta_Xcat+eta_Ycat) %Error of prediction errorMODEL=mean(abs(p_Xcat-data)); RMS_MODEL=(mean((p_Xcat-data).^2))^.5; %Likelihood (start) %likelihood=binopdf(data*5,5, p_Xcat) %REQUIRES the statistics toolbox %otherwise the likelihood needs a longer code such as : LogLikelihoodMODEL=0; for objectNum=1:4 freqXcat=data(objectNum)*nBLOCKS; freqYcat=nBLOCKS-freqXcat; likelihood=nchoosek(nBLOCKS,freqXcat)*p_Xcat(objectNum)^freqXcat*(1-p_Xcat(objectNum))^freqYcat; LogLikelihoodMODEL=[LogLikelihoodMODEL+log(likelihood)]; end if LogLikelihoodMODEL> bestLogLikelihood bestErrorModel=errorMODEL; bestRMS_MODEL=RMS_MODEL; bestLogLikelihood=LogLikelihoodMODEL; bestc=c; end %Likelihood (Finished) end %Test guessing errorGUESS=mean(abs([.5 .5 .5 .5]-data)); RMS_GUESS=(mean(([.5 .5 .5 .5]-data).^2))^.5; LogLikelihoodGUESS=0; for objectNum=1:4 freqXcat=data(objectNum)*nBLOCKS; freqYcat=nBLOCKS-freqXcat; likelihood=nchoosek(nBLOCKS,freqXcat)*0.5^freqXcat*0.5^freqYcat;
39
LogLikelihoodGUESS=[LogLikelihoodGUESS+log(likelihood)]; end %result disp('RESULTS **********') bestErrorModel errorGUESS bestRMS_MODEL RMS_GUESS bestLogLikelihood LogLikelihoodGUESS
Output
data =
0.8000 0.6000 0.6000 0.2000
distMatrix =
0 1 1 2
1 0 2 1
1 2 0 1
2 1 1 0
Xcat =
1 1 1 1
1 1 1 1
1 1 1 1
0 0 0 0
Ycat =
0 0 0 0
0 0 0 0
0 0 0 0
1 1 1 1
simMatrix = ((on teste ici le modèle avec c = 1))
1.0000 0.3679 0.3679 0.1353
0.3679 1.0000 0.1353 0.3679
0.3679 0.1353 1.0000 0.3679
0.1353 0.3679 0.3679 1.0000
eta_Xcat =
40
1.7358 1.5032 1.5032 0.8711
eta_Ycat =
0.1353 0.3679 0.3679 1.0000
p_Xcat =
0.9277 0.8034 0.8034 0.4656
simMatrix = ((on teste ici le modèle avec c = 5))
1.0000 0.0067 0.0067 0.0000
0.0067 1.0000 0.0000 0.0067
0.0067 0.0000 1.0000 0.0067
0.0000 0.0067 0.0067 1.0000
eta_Xcat =
1.0135 1.0068 1.0068 0.0135
eta_Ycat =
0.0000 0.0067 0.0067 1.0000
p_Xcat =
1.0000 0.9934 0.9934 0.0133
RESULTS **********
bestc =
1 ((on retrouve ici surlignés en rouge tous les chiffres calculés auparavant))
bestErrorModel =
0.2000
errorGUESS =
0.2000
41
bestRMS_MODEL =
0.2059
RMS_GUESS =
0.2236
bestLogLikelihood =
-6.1930
LogLikelihoodGUESS =
-6.0389
Sélection de modèles
Nous conseillons pour terminer la lecture de Roberts & Pashler (2000) et de Pitt & Myung (2002)
qui permettent de comprendre la valeur d'un bon ajustement aux données. Un ajustement n'est pas
satisfaisant lorsqu'un modèle sur-ajuste les données, un problème que nous avons mentionné dans
le chapitre 8. Pour cette raison, il est conseillé pour sélectionner un modèle d'utiliser le critère
d'Akaike (AIC, Akaike Information Criterion) ou le critère bayesien (BIC, Bayesian Information
Criterion), qui sanctionnent les modèles trop puissant. En effet, ces critères prennent en compte le
nombre de paramètres intégrés par les modèles afin d’évaluer si le gain offert par un modèle est
suffisamment important pour justifier sa complexité. Il existe d'autres méthodes de sélection
encore plus satisfaisantes (e.g., MDL, Minimum Description Length) expliquées de façon très
claires par Pitt & Myung (2002).
Références
Lamberts, K. (1997). Process models of categorization. In K. Lamberts & D.R. Shanks (Eds.),
Knowledge, concepts and categories. (pp. 371-403).
Cambridge, MA, USA: The MIT Press.
Luce, R. (1963). Detection and recognition. In R. Luce, R. Bush, & E. Galanter (Eds.), Handbook
of mathematical psychology (pp. 103-190). New York, NY : Wiley.
Nosofsky, R. M. (1984). Choice, similarity, and the context theory of classification. Journal of
Experimental Psychology : Learning, Memory, and Cognition, 10, 104-114.
Nosofsky, R. M. (1986). Attention, similarity, and the identification-categorization relationship.
Journal of Experimental Psychology : General, 115, 39-57.
Pitt, M. A., & Myung, I. J. (2002). When a good fit can be bad. Trends in Cognitive Sciences, 6,
421-425.
Roberts, S., & Pashler, H. (2000). How persuasive is a good fit ? A comment on theory testing.
Psychological Review, 107, 358-367.
1
Annexes
ANNEXE 1. Initiation à la programmation sous MATLAB
Style des programmes
Je vous invite à consulter le manuel succinct (13 pages) intitulé "MATLAB Programming Style
Guidelines" de Richard Johnson1, qui décrit les conventions d'écriture de code sous MATLAB. Ces
conventions tiennent en fait en quelques mots : Les variables doivent être écrites en minuscules et
majuscules de la façon suivante : proportions, tempsDeReponse, etc. Les constantes doivent être
écrites en majuscules : CONSTANTE, NOMBRE_MAX, etc. Les noms de vos variables doivent être
explicites : sujetNum pour numéro de sujet, nSujets pour nombre de sujets, et non i, j, ou k. Les noms
de fonctions s'écrivent uniquement en minuscules : fonctioncalcultempsdereponse par exemple.
Les programmes doivent être modularisés au maximum. Pour un programme consistant à aller sur la lune,
le programme devrait être decoller.m, naviguer.m, atterir.m, chacun des fichiers .m listant un ensemble de
commandes MATLAB. La modularité rend le code lisible, et permet de cacher des calculs et des variables
qui ne sont pas intéressantes au premier plan.
Longueur des programmes
Lorsqu'on écrit un programme, il faut tenter d'optimiser le code de façon à ce qu'il ne soit pas trop long, car
plus on écrit de lignes de programmation, plus on a de chances de commettre des erreurs. Un autre conseil,
opposé au premier, réside dans le fait qu'un code très élégant et très court n'est parfois pas très lisible.
Autant faire un code un peu plus long pour faciliter sa compréhension. C'est la clarté qui prime, pas
l'élégance. Un dernier conseil pour la route : "if it ain't broke, don't fix it". Cela signifie que si le code
fonctionne, ce n'est pas la peine d'aller tenter de le réécrire pour l'améliorer, au risque de faire bugger un
programme qui fonctionnait très bien avant votre intervention !
Arrêt d'urgence, stopper l’exécution d’un script
Si vous lancez un programme et que son exécution dure plus longtemps que prévu (le code comporte une
erreur, tous les résultats intermédiaires s’affichent, etc.), vous pouvez le stopper en appuyant sur les touches
ctrl + c (! + c sur mac). Si toutefois cette solution s’avère inefficace, il vous reste la solution extrême : ctrl
+ alt + del (option + ! + esc sur mac) pour ouvrir le gestionnaire de tâches.
Initiation
Téléchargez le programme annexe1.m et ouvrez le dans MATLAB. MATLAB est constitué de sous-
fenêtres. Gardez cette organisation de fenêtre par défaut. Si par mégarde vous déplacez vos fenêtres, vous
pouvez retrouver cette organisation utile par défaut dans le menu Desktop/Desktop Layout/Default.
Le code commence par un entête commenté grâce à des symboles %. Toute ligne commençant par un %
n'est pas lue par MATLAB. Il vous est fortement recommandé d’utiliser cette technique afin de commenter
le plus précisément possible votre code. De tels commentaires sont utiles lorsque vous (ou un autre
utilisateur) relisez le programme afin d'en faciliter la (re)lecture. Chacun des morceaux de programme (i.e.,
des cellules) est indiqué par le mot "Code". Le résultat de l'exécution du code est indiqué par le mot
"Output". La section "Output" vous permet de lire ce manuel afin d'assimiler la logique de la
programmation MATLAB sans forcément avoir MATLAB à votre disposition.
Le programmeur doit faire un descriptif de son programme dans une entête telle que : % Ce programme permet d'apprendre à utiliser MATLAB % Création 03/03/06. Mise à jour 08/09/12. Auteur : F. Mathy.
Une ligne précédée du symbole % n'est pas lue par Matlab, symbole à utiliser abondamment de manière à
1 http://www.datatool.com/downloads/matlab_style_guidelines.pdf
2
commenter le code et le rendre plus clair.
Pour apprendre Matlab pas à pas, nous recommandons de tester le code cellule par cellule. Dans le menu,
choisir Cell/Enable cell mode. Une cellule commence par %% (deux symboles %, suivis d'un espace).
Lorsque vous placez le curseur sur une cellule, la cellule est surlignée en jaune. Cliquez sur Cell/Evaluate
Current Cell dans le menu pour lancer le bout de programme contenu dans la cellule. Observez ce qui se
produit puis testez la cellule suivante. Pour lancer le fichier entièrement, cliquez sur Debug/Save File and
Run ...
Aides
Pour obtenir la description d’une commande, tapez « help nomdecommande », par exemple : « help clear »
ou « help clc » dans la fenêtre de commandes (Command Window)... puis validez. Une autre façon
d'obtenir de l'aide est de cliquer sur l'icône dans le menu du haut. Ce menu contient par ailleurs de
nombreuses astuces et démonstrations (vidéos, fichiers Matlab, fichiers Pdf) utiles, que l’on peut tester en
tapant directement « demo » dans la fenêtre de commandes.
Reset des variables et de l'écran
Avant de commencer, il est important de supprimer d’éventuelles variables résiduelles et, pour plus de
clarté, d’effacer le contenu de la fenêtre de commande :
Code clear all % Efface toutes les variables. clc % Efface le contenu de la fenêtre de commandes. % Nous aurions pu écrire les deux commandes sur une seule ligne comme suit : clear all, clc % La virgule sert à combiner plusieurs commandes.
Output >>
Constantes
Il est possible d’assigner manuellement une valeur à une constante :
Code A=1.20 B= 1.30 ; % Le ';' permet d’accélérer l’exécution du code en n’affichant pas les résultats à l'écran. MATLAB mémorise quoiqu'il en soit tous les calculs effectués.
Output A = 1.2000 >>
Notez que les deux constants A et B sont stockées dans l’espace de travail ou workspace. Vous pouvez
copier-coller "C =A+B" dans la fenêtre de commande...ou passez à la cellule suivante.
3
Code clc C =A+B
Output C = 2.5000 >>
Formats
Les nombres à virgule sont parfois trop longs et illisibles. La commande format short/long permet de gérer
leur présentation à l’écran. La commande format long détermine un format d’affichage de type long alors
que la commande format short affiche des valeurs arrondies tout en conservant en mémoire la valeur
exacte. Pour le vérifier, on peut tester l’égalité entre la valeur de pi au format court (3.1416) et la valeur
d’une constante égale à 3.1416 à l’aide de l’opérateur ==.Si la réponse est 0, cela signifie bien que malgré
un format court, les valeurs exactes des constantes sont bien conservées en mémoire.
Code clear all, clc A=pi; format long % détermine un format d’affichage de type long. A format short % détermine un format d’affichage de type court. A B=3.1416 A==B % teste si les valeurs de A et B sont égales. Output A = 3.141592653589793 A = 3.1416 B = 3.1416 ans = 0
4
Matrices
Les matrices sont des tableaux de données sur lesquels il est possible d’effectuer des opérations. Pour
définir une matrice, on utilise les symboles [] afin de délimiter le début et la fin de ses éléments, l'espace
(ou la virgule) pour séparer les valeurs sur une ligne et le symbole ; pour délimiter les lignes. Les données
peuvent être assignées manuellement, par incrémentation en utilisant le symbole ":" ou par concaténation
verticale ou horizontale de matrices. Certaines fonctions permettent de générer des matrices particulières.
Par exemple la fonction magic(n) crée une matrice de dimension n par n sur le principe du carré magique
pour lequel les sommes de chaque colonne, chaque ligne, et chaque diagonale sont égales. La fonction
randn(m,n) tire aléatoirement m lignes de n nombres (i.e., n colonnes) à partir d'une distribution normale de
scores z (les scores z sont normalement distribués, de moyenne 0 et d'écart-type 1).
Code clear all, clc a=[7 9 11] % Ici, on entre manuellement toutes les valeurs (7, 9, 11) de a. b=[7:11] % Ici, on attribue à b toutes les valeurs de 7 à 11, par défaut l’incrémentation est de 1. c=[7:2:11] % On peut spécifier l'incrémentation, ici 2. d=[7 8 9;4:6;1:3] % ';' spécifie les lignes dans la matrice d. Les espaces définissent les colonnes. e=[c c] % Crée la matrice e par concaténation horizontale de c. f=[c;c] % Idem avec une concaténation verticale. g=e' % Transpose les données. % si on essaie g=e'' on obtient e à l’identique par double transposition
Output a = 7 9 11 b = 7 8 9 10 11 c = 7 9 11 d = 7 8 9 4 5 6 1 2 3 e = 7 9 11 7 9 11
5
f = 7 9 11 7 9 11 g = 7 9 11 7 9 11 >>
Matrices (suite). Commandes magic et randn
Code clear all, clc a=magic(5) % Crée une matrice de dimension 5 par 5 sur le principe du carré magique pour lequel la somme sur chaque colonne, chaque ligne, et chaque diagonale est égale. sumColumns=sum(a) % Somme les colonnes de la matrice a. sumRows=sum(a') % Somme les lignes de a. sumDiagonal=sum(diag(a)) % Somme les éléments de la diagonale principale de a. c=randn(1,1000) % Tire aléatoirement 1 ligne de 1000 nombres (i.e., 1000 colonnes) à partir d'une distribution normale de scores z (les scores z sont normalement distribués, de moyenne 0 et d'écart-type 1). hist(c) % Génère un histogramme de la distribution de la matrice c.
Output a = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 sumColumns = 65 65 65 65 65 sumRows = 65 65 65 65 65
6
sumDiagonal = 65 >>
Manipulations de matrices
Voici quelques exemples d’opérations simples sur des matrices. Nous verrons qu’il est possible d’extraire
ou de modifier de manière sélective un ou plusieurs élément(s) d’une matrice, selon une position précise
dans la matrice, selon une colonne ou une ligne. Ainsi il devient facile de calculer des moyennes de
colonnes ou de lignes (scores moyens par sujet ou par item par exemple), de calculer une moyenne globale
ou selon des critères plus fins.
Exemple 1
Code %% clear all, clc a=magic(5) aTransposed=a' a = aTransposed' chosen1=a(6) % Crée la variable chosen1 égale à l'élément en sixième position (en parcourant un ordre par colonne) de la matrice a. chosen2=a(1:9) % Crée la matrice chosen2 à partir des éléments 1 à 9 (en suivant un ordre par colonne) de la matrice a. chosen3=a(:) % Crée la matrice chosen3 à partir de tous les éléments de la matrice a regroupés en une seule colonne d'éléments, on obtient ainsi ce qu’on appelle un vecteur. chosen4=a([1 2 9]) % Sélectione des éléments précis de a. meanByCol=mean(a) % Renvoie par défaut les moyennes de chacune des colonnes. grandMean=mean(mean(a)) % Pour obtenir la moyenne de l’ensemble des éléments de a, on peut calculer la moyenne des moyennes des colonnes. grandMeanSimpler=mean(a(:))% Ou plus simplement en calculant la moyenne du vecteur de a. copy_Of_a=a; line1=copy_Of_a(1,:) % Renvoie la première ligne, équivalent à copy_Of_a(1,[1:5]) col1=copy_Of_a(:,1) % Renvoie la première colonne.
7
copy_Of_a(1,1)=0 % Assigne la valeur 0 au premier élément. copy_Of_a(:,1)=[] % Efface la première colonne.
Output
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
aTransposed =
17 23 4 10 11
24 5 6 12 18
1 7 13 19 25
8 14 20 21 2
15 16 22 3 9
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
chosen1 =
24
chosen2 =
17 23 4 10 11 24 5 6 12
chosen3 =
17
23
4
10
11
24
5
6
12
18
1
7
8
13
19
25
8
14
20
21
2
15
16
22
3
9
chosen4 =
17 23 12
meanByCol =
13 13 13 13 13
grandMean =
13
grandMeanSimpler =
13
line1 =
17 24 1 8 15
col1 =
17
23
4
10
11
copy_Of_a =
0 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
9
copy_Of_a =
24 1 8 15
5 7 14 16
6 13 20 22
12 19 21 3
18 25 2 9
>>
Exemple 2 : résultats obtenus par trois participants
Prenons l’exemple d’un test dans lequel trois participants ont réalisé six essais chacun. Il est très simple de
procéder automatiquement à des calculs de scores selon les modalités qui nous intéressent. On peut ainsi
obtenir les scores moyens des trois participants pour chaque essai, tous les scores du premier participant
seulement ou sa moyenne sur l’ensemble des essais ou encore les scores et la moyenne pour un essai
particulier.
Code format short clear all, clc results =[1 2 3 1 2 3 % scores du 1er participant 2 2 2 2 2 2 % scores du 2nd participant 4 5 4 5 4 5]; % scores du 3ème participant meanByTrial = mean(results) % scores firstParticipantOnly = results(1,:) meanFirstParticipantOnly = mean(firstParticipantOnly) firstTrialOnly = results(:,1) meanFirstTrialOnly =mean(firstTrialOnly)
Output meanByTrial = 2.3333 3.0000 3.0000 2.6667 2.6667 3.3333 firstParticipantOnly = 1 2 3 1 2 3 meanFirstParticipantOnly = 2 firstTrialOnly = 1 2 4
10
meanFirstTrialOnly = 2.3333 >>
Fonction find
Cette fonction peut aider à retrouver automatiquement la position des éléments vérifiant une condition
donnée. Find(matrice==1) recherche tous les éléments de la matrice égaux à 1 et renvoie leur position.
Code clear all, clc results=[1 2 3 1 2 3 2 2 2 2 2 2 4 5 4 5 4 5]; find(results==3) % Renvoie la position des éléments égaux à 3, selon une lecture par colonne (par défaut). [ligne,colonne]=find(results==3) % Position des éléments égaux à 3 selon la ligne et la colonne. results(find(results==3)) = 3.1 % Cherche et remplace tous les scores égaux à 3 en 3.1. Notez que cette technique de vectorisation permet de réaliser cette opération sans utiliser de boucle.
Output ans = 7 16 ligne = 1 1 colonne = 3 6 results = 1.0000 2.0000 3.1000 1.0000 2.0000 3.1000 2.0000 2.0000 2.0000 2.0000 2.0000 2.0000 4.0000 5.0000 4.0000 5.0000 4.0000 5.0000 >>
Taille des matrices : fonction size et length
11
Quelques astuces permettant d’évaluer différent paramètres de taille d’une matrice. La fonction size()
renvoie la longueur en lignes et en colonnes d’une matrice, la fonction length() renvoie la plus grande de
ces deux longueurs.
Code clear all, clc results=[1 2 3 1 2 3 2 2 2 2 2 2 4 5 4 5 4 5]; size_results=size(results) %Renvoie par défaut le nombre de lignes et de colonnes. number_Of_Rows=size(results,1) % 1 est un paramètre additionnel qui indique qu'on souhaite uniquement le nombre de lignes de la matrice results. number_Of_Columns=size(results,2) % 2 pour obtenir le nombre de colonnes. max_size=length(results) % Renvoie la plus grande des longueurs, soit le nombre de lignes soit le nombre de colonnes.
Output
size_results =
3 6
number_Of_Rows =
3
number_Of_Columns =
6
max_size =
6
Nombres aléatoires distribués uniformément : fonction rand
Dans cet exemple, nous avons généré une distribution aléatoire uniformément distribuée, puis
sommairement testé son uniformité en calculant les moyennes par colonne, par ligne et globale.
Code clear all, clc distribution1=rand(10,4) meansByColumn_distribution1=mean(distribution1) meansByRows_distribution1=mean(distribution1') grandMean_distribution1=mean(mean(distribution1))
12
Output distribution1 = 0.8308 0.0540 0.7943 0.0838 0.5853 0.5308 0.3112 0.2290 0.5497 0.7792 0.5285 0.9133 0.9172 0.9340 0.1656 0.1524 0.2858 0.1299 0.6020 0.8258 0.7572 0.5688 0.2630 0.5383 0.7537 0.4694 0.6541 0.9961 0.3804 0.0119 0.6892 0.0782 0.5678 0.3371 0.7482 0.4427 0.0759 0.1622 0.4505 0.1067 meansByColumn_distribution1 = 0.5704 0.3977 0.5207 0.4366 meansByRows_distribution1 = 0.4407 0.4141 0.6927 0.5423 0.4609 0.5318 0.7183 0.2899 0.5239 0.1988 grandMean_distribution1 = 0.4814 >>
Nombres aléatoires distribués normalement : fonction randn
Dans cet exemple, nous avons généré une distribution aléatoire normalement distribuée, puis
sommairement testé sa normalité en calculant les moyennes par colonne ainsi que la moyenne globale.
Code d2=randn(10,4) meansD2=mean(d2) grandMeanD2=mean(meansD2)
Output
d2 =
0.5377 -1.3499 0.6715 0.8884
1.8339 3.0349 -1.2075 -1.1471
-2.2588 0.7254 0.7172 -1.0689
0.8622 -0.0631 1.6302 -0.8095
0.3188 0.7147 0.4889 -2.9443
-1.3077 -0.2050 1.0347 1.4384
13
-0.4336 -0.1241 0.7269 0.3252
0.3426 1.4897 -0.3034 -0.7549
3.5784 1.4090 0.2939 1.3703
2.7694 1.4172 -0.7873 -1.7115
meansD2 =
0.6243 0.7049 0.3265 -0.4414
grandMeanD2 =
0.3036
>>
Tests de comparaisons
Vous pouvez utiliser les différents opérateurs relationnels : supérieur à >, supérieur ou égal à >=,
inférieur à <, inférieur ou égal à <=, égal à == ou encore différent de ~= afin de comparer entre eux les
éléments de deux matrices. Remarquez que la notation == correspond à un test d'égalité, alors que =
correspond à l'attribution d'une valeur à une variable. Le test réalisé par ce type d’opérateurs compare un à
un les éléments puis renvoie pour leurs positions respectives les valeurs 1 (test vérifié) ou 0 (test non
vérifié).
Code e1=[1:5] e2=[5:-1:1] differents=(e1~=e2) % Compare les 2 matrices et renvoie la valeur 1 lorsque leurs éléments sont différents pour une même position. equals=(e1==e2) greaterThanOrEqualTo=(e1>=e2)
Output
e1 =
1 2 3 4 5
e2 =
5 4 3 2 1
differents =
1 1 0 1 1
equals =
0 0 1 0 0
14
greaterThanOrEqualTo =
0 0 1 1 1
>>
Opérateurs logiques.
Vous disposez également sur Matlab des différents opérateurs logiques comme par exemple : et logique &,
ou inclusif |, ou exclusif xor, différent ~=. Les opérateurs logiques s’appliquent à des matrices de même
taille, en renvoyant pour chaque position le résultat du test logique demandé : 1 ou 0.
Code clear all, clc result1=[0 0 1 1] | [0 1 0 1] % Ou logique result2=xor([0 0 1 1],[0 1 0 1]) % Ou exclusif logique result3=[0 0 1 1] & [0 1 0 1] % Et logique result4= ([0 0 1 1]~= [0 1 0 1]) % different
Output
result1 =
0 1 1 1
result2 =
0 1 1 0
result3 =
0 0 0 1
result4 =
0 1 1 0
>>
Texte ou chaînes de caractères
En programmation, vous pouvez être amené à manipuler des données de type texte, en les stockant
simplement, en les utilisant ou en les modifiant. Par exemple un programme peut prévoir d’enregistrer des
données entrées par l’utilisateur, son nom, son âge, etc.
Code clear all, clc name=input('Please enter your name > ','s'); % la fonction input permet de demander à l’utilisateur d’entrer une réponse au message affiché à l’écran. Le paramètre "s" permet d'enregistrer la réponse du sujet
15
comme une chaîne ("s" pour string). sentence=['Hello ',name]; disp(sentence) age=input('Please enter your age > ') ; fprintf('You''re young! I mean it... %d is young!\n', age) % "%d" attend un nombre entier. "\n" renvoie un saut de ligne.
Output
Please enter your name > Adam
Hello Adam
Please enter your age > 80
You're young! I mean it... 80 is young!
>>
>>
Chaînes de caractères OU Matrices de caractères
Les chaînes de caractères sont représentées par un ensemble de caractères, lettres, chiffres ou autres
caractères, que l’on encadre par des ‘apostrophes‘. Matlab les intègre alors comme chaînes de caractères,
dont il est alors possible d’extraire, modifier, supprimer des éléments (isolément ou par groupes). On peut
également concaténer plusieurs chaînes de caractères entre-elles, c'est-à-dire les assembler en une nouvelle.
Code clear all, clc myMiniAlphabet='abcdefg' %Chaque lettre est un élément d'une matrice de lettres. myMiniAlphabet(8:9)='hi' myMiniAlphabet(9)='' string1='Adam',string2='Joe ' %Noter qu'on ajoute un espace après Joe pour que string1 et string2 aient la même longueur. strings=[string1 string2] % Puisque string1 et string2 sont des matrices, on peut les concaténer dans une nouvelle matrice de 8 colonnes. strings2=[string1;string2] % Cela fonctionne aussi en 2 lignes de 4 colonnes. string1='Adam',string2='Joe' strings=[string1 string2] % La nouvelle matrice fait 7 colonnes.
Output myMiniAlphabet = abcdefg myMiniAlphabet = abcdefghi
16
myMiniAlphabet = abcdefgh string1 = Adam string2 = Joe strings = AdamJoe strings2 = Adam Joe string1 = Adam string2 = Joe strings = AdamJoe >>
Cellules et structures.
Matlab ne permet pas seulement de créer et de faire des opérations sur les matrices, il est également
possible de manipuler des cellules ou des structures.
Les cellules {} peuvent être comparées à des boites dans lesquelles on peut ranger ce que l’on veut, du
texte, des nombres, des matrices, et même des cellules.
Code clear all, clc string1='Adam',string2='Ed' strings_onSeparateLines={string1;string2} % les crochets {} permettent de définir le contenu d’une cellule myCell={strings_onSeparateLines; [1 1000]; 'XXX'} myCell{1,2}='0000'
17
contenu_de_myCell_ligne2_col1=myCell{2,1} first_element_of_myCell_line2_col1=myCell{2,1}(1)
Output
string1 =
Adam
string2 =
Ed
strings_onSeparateLines =
'Adam'
'Ed'
myCell =
{2x1 cell }
[1x2 double]
'XXX'
myCell =
{2x1 cell } '0000'
[1x2 double] [] %Remarque : les crochets[] indiquent une cellule vide
'XXX' []
contenu_de_myCell_ligne2_col1 =
1 1000
first_element_of_myCell_line2_col1 =
1
>>
>>
Code
Output
Structures de contrôle
Si les exemples suivants sont simplistes, l’important est de tenter de prédire les résultats.
Sous Matlab, il vaut mieux profiter des matrices pour aller plus vite. Par exemple, on peut manipuler des
18
matrices et obtenir le même résultat qu’en écrivant une boucle.
Code clear all, clc for num=1:4 num2=num-1 end num=[1:4] num2=num-1 test=[1 2 4] for i=test j=i-1 end j=[] for i=test j=[j,i-1] end
Boucles emboîtées k=[] for i=test for j=test k=[k,j+i] end end i=1 while i<5 i=i+1; disp(i) end total=10 switch total case 10 disp('The total is ten.') case 20 disp('The total is twenty.') otherwise disp('I don''t know what the total is.') end
Output
num2 =
0
num2 =
19
1
num2 =
2
num2 =
3
num =
1 2 3 4
num2 =
0 1 2 3
test =
1 2 4
j =
0
j =
1
j =
3
j =
[]
j =
0
j =
0 1
20
j =
0 1 3
k =
[]
k =
2
k =
2 3
k =
2 3 5
k =
2 3 5 3
k =
2 3 5 3 4
k =
2 3 5 3 4 6
k =
2 3 5 3 4 6 5
k =
2 3 5 3 4 6 5 6
k =
2 3 5 3 4 6 5 6 8
21
i =
1
2
3
4
5
total =
10
The total is ten.
>>
22
Fonctions
Sur Matlab vous pouvez avoir l’utilité d’une fonction si spécifique qu’elle n’existe pas dans la gamme des
fonctions Matlab, il est alors envisageable d’en créer une. Ainsi, par exemple sur un code indépendant,
vous pourriez créer un code remplissant cette fonction, et vous en servir dans votre programme principal.
Imaginons que l'on veuille créer une fonction permettant à la fois d'additionner et de multiplier deux
variables x1 et x2, qui seront donc des arguments d’entrée et pour lesquels elle devra fournir les arguments
de sorties attendus. Une fonction sans argument est appelée un script ou une procédure. Un script est une
liste de commande qui ne dépend d'aucune valeur particulière. Afficher une fenêtre noire en plein écran
pendant 1 seconde par exemple requiert un script, et non une fonction. La frontière est souvent perméable.
On pourrait très bien créer une fonction pour afficher une fenêtre noire sur l’un de deux écrans connectés à
l’ordinateur en envoyant un argument d'entrée correspondant au numéro d'écran.
clear all, clc x1=1; x2=1;
[y1,y2]= annexe1function (x1,x2) % Cette commande appelle la fonction
annexe1function avec deux arguments d'entrée (x1,x2) et deux arguments de sortie [y1,y2]. Notez que c'est nous qui avons nommé notre fonction
annexe1function au moment où nous avons sauvegardé le fichier .m. Son nom n'est pas assez explicite car sa véritable fonction est d'additionner et de multiplier jusqu'à 3 nombres. Son nom devrait refléter sa fonction exacte, mais ici le choix de son appellation s’est uniquement porté sur l’idée que 1) elle réfère au chapitre 1 et que 2) elle est sans intérêt et absurde. Output y1 = 2 y2 = 1
Sur Matlab ouvrez annexe1function afin d'en étudier le code... nargin est un paramètre testable par la
fonction elle-même, qui indique combien d'éléments en entrée ont été donnés par l'utilisateur. Si
l’utilisateur tape simplement chap1dummyfunction, la fonction n’a pas de paramètre d’entrée et nargin vaut
0 automatiquement. Si l’utilisateur tape chap1dummyfunction(23), la fonction a un paramètre d’entrée (23)
et nargin vaut 1. En fonction de nargin, on peut améliorer l’applicabilité de la fonction à tous les cas
possibles d’utilisation. Il suffit d’associer des portions de code : par exemple, ici, il suffit d’utiliser les
valeurs neutres 0 pour l'addition et 1 pour la multiplication pour que la fonction utilisée avec un seul
argument d’entrée fonctionne.
Autre essai ...
[y1Other,y2Other]= annexe1function (3,3,3) % La fonction fonctionne avec 3 arguments d'entrée. Output
23
y1Other = 9 y2Other = 27 >>
Si annexe1function n'avait eu qu'un seul argument de sortie, on aurait écrit: y=
chap1dummyfunction(x1,x2).
Attention, un bon programmeur connait les fonctions disponibles préexistantes ! La fonction
annexe1function est très peu puissante, puisqu'elle se limite à 3 arguments d'entrée. Pourquoi avoir donc
créé une fonction qui de surcroît mélange sans raison valable une addition et une multiplication. Autant
utiliser les deux fonctions pré-construites suivantes : Code clear all, clc y1 = sum([1 1]) y2=prod([1 1]) Output y1 = 2 y2 = 1 >>
Récapitulatif
Voici un programme récapitulatif permettant de simuler le tirage au sort de x échantillons de n sujets,
associer aux x ! n mesures un QI tiré au sort, corriger des scores automatiquement, faire des statistiques
etc. Sur Matlab ouvrez le script simuqi.m et lancez le avec le symbole triangulaire vert "Play", ou tapez
simuqi dans la command Window ou insérez la commande simuqi dans un autre script .m. Ce sont les 3
façons d'appeler un script.
Code
%% IQ simulation % Generate x samples of n scores and eventually simulate the central limit theorem. % IQs are randomly drawn from a normal distribution of mean 100 and standard % deviation 15. clear all, clc MEAN_IQ=100; STD_IQ=15;
24
nSamples=input('Please enter the number of samples > ') ; nSubjects=input('Please enter the number of subjects per sample > ') ; data=randn(nSubjects,nSamples); data=MEAN_IQ+ data*STD_IQ; sampleMeans=mean(data); iq_freq_classes=hist(sampleMeans,9) % On demande les effectifs de l'histogramme pour 9 classes, sans tracer l’histogramme; la commande hist(sampleMeans, 9) (sans iq_freq_classes= la précédent) permet de tracer l'histogramme. standardError_predicted=15/sqrt(nSubjects) standardError_real=std(sampleMeans) Output Please enter the number of samples > 50 Please enter the number of subjects per sample > 100 iq_freq_classes = 3 1 9 12 13 6 3 2 1 standardError_predicted = 1.5000 standardError_real = 1.5629
Conseil : exécutez plusieurs fois le programme avec des valeurs de plus en plus élevées pour nSamples et
nSubjects, afin de vérifier le théorème de la limite centrale. La dispersion devrait approcher :
erreur standard =15/racine(nSubjects)
ASTUCES DE PROGRAMMATION sous MATLAB
- On souhaite définir des zones virtuelles d'une image. L'image fait 210 pixels en largeur et 320 pixels en
hauteur. Comment placer un quadrillage de 6 champs horizontaux à équidistance. La solution pour la
largeur est :
Code
>> linspace(0,210,7)
Output
ans =
0 35 70 105 140 175 210
On a utilisé 7 bornes pour obtenir 6 intervalles
- Pour obtenir une liste de toutes les variables, on utilise la commande :
25
Code
>> whos
Si on souhaite que cette liste devienne une variable, on peut enregistrer le contenu de whos :
Code
>> maVariable = whos
Cela permet de faire toutes sortes de calculs sur la liste de variables... par exemple, l'espace total requis en
mémoire par l'ordinateur pour l'ensemble des variables.
- Si vous avez déjà une foule de variables dans votre programme, il se peut que vous ne sachiez plus quel
nom inventer pour votre variable. Une fonction pratique est genvarname, permettant de trouver un nom
approprié qui ne recouvre ni un nom de variable déjà utilisé dans votre programme, ni un nom de variable
correspondant à une fonction MATLAB. Lorsque plusieurs noms de variable sont donnés en entrée,
genvarname propose des noms qui ne sont pas en conflit.
>> varnamelist = genvarname({'col','col','col','col','col'})
varnamelist =
'col' 'col1' 'col2' 'col3' 'col4'
- Pour recopier des chiffres identiques, afin de coder des données selon des conditions expérimentales par
exemple, on utilise repmat :
>> A = [1 2]
A =
1 2
>> B =repmat(A, [10 1])
B =
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
>> B=B(:)
B =
1
1
26
1
1
1
1
1
1
1
1
2
2
2
2
2
2
2
2
2
2
- Pour faire des commentaires multi-lignes : %{ ... %}
- Les commentaires "professionnels" en anglais ne sont pas fait à la 3e personne : on utilise "Calcultate
average RT au lieu de "Calculates average RT"
- Pour obtenir une liste des modules installés : ver
- Pour obtenir une liste de fonctions se rapportant à l'addition : lookfor
- Vectoriser le plus possible pour accélérer la vitesse d'exécution du programme (et pour plus de lisibilité), %loops should be avoided: n=1:10 x=n*pi %is better than a loop like 'for n=1:10 etc.'
au lieu de % for n=1:10 % x(n)=n*pi % end
et pré-allouer l'espace demandé par une variable par les fonctions zeros, ones ou nan pour : % %arrays should be preallocated %x=zeros(1,10); n=1:10 x=n*pi
top related