nbgrader : évaluation et correction automatique de classeurs
nbgrader est un outil développé par et pour les professeurs pour créer et évaluer des devoirs riches et interactifs dans des classeurs Jupyter.
nbgrader peut être utilisé seul pour créer des devoirs. Il permet à partir d'une version complète rédigée par le professeur d'extraire automatiquement un document que l'élève devra compléter et rendre. Le professeur aura la charge de collecter tous les travaux élèves et de les placer dans une arborescence adéquate. A l'issue de quoi, nbgrader pourra réaliser l'évaluation automatique de tous les travaux élèves et les noter selon le barême établi par le professeur. Le professeur peut prévoir des questions plus ouvertes qu'il évaluera manuellement, en complément de la procédure automatique.
Lorsqu'il est utilisé conjointement avec jupyterHub (version multi-utilisateurs de jupyter), la procédure de distribution et de récupération des devoirs est automatisée ce qui rend l'ensemble du processus totalement automatique !
Dans la vidéo ci-dessous - en anglais - vous aurez une démonstration des potentialités de cet outil.
Complément : Documentation officielle de nbgrader
Pour plus d'informations sur nbgrader, je vous renvoie à la documentation en ligne.
Attention :
Ce guide s'adresse à des personnes à l'aise avec python, jupyter et l'installation de modules avec PIP.
nbgrader sur Jupyter
Nous supposerons dans cette partie que vous disposez d'une installation Jupyter opérationnelle. J'ai réalisé tous mes tests sous Linux à partir d'une image Docker jupyter/minimal-notebook.
Il n'est bien sûr pas nécessaire d'utiliser docker et vous pouvez tout à fait utiliser votre installation habituelle de Jupyter (anaconda ou autre).
Installation de nbgrader
Méthode : Installation sur le système
nbgrader nécessite la version 1.2.x de SQLAlchemy. Il ne fonctionnera pas avec la version 1.3 ou ultérieure. Il faut donc commencer par installer cette version particulière
pip install SQLAlchemy==1.2.19
On installe ensuite nbgrader de manière tout à fait classique
pip install nbgrader
On active enfin l'extension dans jupyter :
jupyter nbextension install --sys-prefix --py nbgrader --overwrite
jupyter nbextension enable --sys-prefix --py nbgrader
jupyter serverextension enable --sys-prefix --py nbgrader
Créez le dossier d'échange
mkdir -p /srv/nbgrader/exchange
chmod ugo+rw /srv/nbgrader/exchange
Méthode : Configuration initiale
Créer le fichier de configuration nbgrader_config.py dans le dossier .jupyter de votre espace personnel (ou autre dossier dans le path de jupyter) avec le contenu suivant.
c = get_config()
c.Exchange.course_id = "cours_MON_LOGIN"
c.Exchange.root = '/home/MON_LOGIN'
c.IncludeHeaderFooter.header = "source/header.ipynb"
Si vous n'utilisez pas docker, vous adapterez le chemin '/home/MON_LOGIN' en indiquant l'emplacement de vos classeurs jupyter.
Méthode : Créer un fichier d'entête
Le fichier de configuration fait référence à un classeur source/header.ipynb qu'il faut créer dans votre arborescence Jupyter. Cette entête sera ajoutée systématiquement aux classeurs qui seront générés pour les élèves. Il peut par exemple contenir une cellule markdown avec un titre et des instructions pour la remise du travail au professeur via l'ENT.
Il faut créer ce fichier, même de manière très sommaire, avant de pouvoir commencer à utiliser nbgrader. Une fois cette étape réalisée, vous pouvez commencer la découverte de ce formidable outil ! A ce stade, votre environnement jupyter doit ressembler à ceci :
Vous remarqez la présence
du dossier source qui contient header.ipynb
des boutons Formgrader et Assignments dans les onglets du haut
L'installation est terminée. Redémarrez Jupyter afin de prendre en compte les modifications.
Utiliser nbgrader
Dans cette partie, nous allons
créer un devoir avec nbgrader
créer deux élèves factices
leur distribuer le devoir
fabriquer les réponses et les récupérer
évaluer les réponses
Créer un devoir
Méthode :
Cliquez sur le bouton Formgrader. La fenêtre suivante doit apparaître. Si vous avez une erreur 404, peut-être n'avez-vous pas redémarré Jupyter suite à l'installation ?
Cliquez sur le bouton Add new assignment pour créer un nouveau devoir.
Saisissez le nom du devoir SANS ESPACES ni caractères spéciaux. Disons testPremier.
Notre devoir est à l'état de brouillon. Nous devons le fabriquer en cliquant sur testPremier. testPremier est un dossier créé dans l'arborescence Jupyter dans le dossier source. Il peut contenir un ou plusieurs classeurs notebook.
Exemple : Écrire une fonction de test de primalité
Dans notre exemple, nous allons demander aux élèves d'écrire une fonction testant si un entier n passé en paramètres est premier.
Le professeur va écrire ses instructions et la fonction qu'il souhaite faire réaliser :
from math import sqrt
def isPrime(n):
### BEGIN SOLUTION
if n==2 or n==3:
return True
if n%2 == 0 or n<=1:
return False
d=3
while n%d!=0 and d <= sqrt(n):
d+=2
return n%d!=0
### END SOLUTION
Attention : Balise BEGIN et END SOLUTION
Vous remarquez dans le code professeur les commentaires ### BEGIN SOLUTION et ### END SOLUTION
Ces commentaires indiquent à nbgrader le code qui devra être retiré des classeurs élèves. Il est important de respecter cette syntaxe à la lettre.
Exemple : Écrire les tests de validation
Il faut à présent écrire les tests permettant de valider la fonction écrite par l'élève. On utilise pour cela la commande assert.
Voici un exemple
assert isPrime(5) == True
assert isPrime(9) == False
assert isPrime(17) == True
assert isPrime(21) == False
### BEGIN HIDDEN TESTS
assert isPrime(0) == False
assert isPrime(1) == False
assert isPrime(2) == True
assert isPrime(3) == True
### END HIDDEN TESTS
Attention : Balises BEGIN et END HIDDEN TESTS
Vous remarquez la encore la présence de balises spéciales qu'il faudra reproduire à l'identique : La partie du code comprise entre ### BEGIN HIDDEN TESTS
et ### END HIDDEN TESTS
sera masquée sur les classeurs élèves. Cela permet de ne pas leur dévoiler sur quelles valeurs sera évaluée leur fonction et ainsi tester quelques cas limites auxquels ils n'auraient pas forcément pensé.
Le classeur du professeur est terminé. Voilà ce que vous devez obtenir à ce stade :
Méthode : Editez les métadonnées des cellules
A présent il faut indiquer quelle cellule devra être évaluée, quelle cellule devra être utilisée par les tests et quelles cellules ne doivent pas être modifiées. Pour cela, il faut commencer par faire apparaître la barre d'outils des cellules dans le menu View / Cell Toolbar / Create assigment
Sélectionnez
Autograded answer pour la cellule contenant la fonction isPrime à compléter par les élèves
Autograder tests pour la cellule contenant les tests à réaliser. Vous indiquez alors le nb de points désiré.
Read-only pour les cellules qui ne devront pas être modifiées.
Voici ce que cela donne :
Complément : Vérification
Cliquez sur le bouton Validate dans la barre d'icônes pour vérifier que votre fonction passe bien les tests ! ! Le devoir est terminé, tout est prêt pour l'étape suivante. N'oubliez pas d'enregistrer le classeur avant de quitter la page.
Créer deux élèves factices
Il nous manque des élèves ! nous allons en créer deux. Pour cela, sur la page d'acceuil de Jupyter, retournez sur l'outil Formgrader puis Manage Students. Cliquez sur Add new student pour ajouter un élève.
Générer le devoir pour les élèves
Retourner sur la page Formgrader
puis cliquez sur le bouton generate. La fenêtre de log vous indique que tout s'est bien passé - j'espère ! et deux nouvelles icônes sont apparues. Cliquez sur la loupe (preview) pour visualiser le classeur que vous distribuez aux élèves.
Comme vous le voyez :
L'entête header à été ajoutée
Le code solution a été enlevé et remplacé par un commentaire invitant les élèves à compléter
Le code de validation est proposé sans la partie que vous avez choisi de masquer
Les cellules marquées en lecture seule ne sont pas modifiables !
Distribuer le devoir
Le devoir ainsi généré se trouve dans un dossier release créé pour l'occasion. Il contient le dossier testPremier avec le fichier DS1.ipynb.
Cliquez sur le bouton Release.
A vous de distribuer le ou les documents aux élèves par le moyen de votre choix (messagerie, ENT etc...).
Remarque :
C'est sur cette partie de distribution et la suivante pour la récupération que l'outil jupyterHub se révèle particulièrement pertinent car il automatise complètement cette partie. Nous verrons la configuration de jupyterHub un peu plus tard dans ce tutoriel. Néanmoins il n'est pas nécessaire de l'utiliser. C'est ce que nous allons voir maintenant.
Récupérer les travaux des élèves
Fondamental :
La procédure décrite ici concerne les installations hors jupyterHub. Si vous disposez d'un serveur jupyterhub, la récupération des travaux élève est automatique en cliquant sur le bouton collect.
La récupération des travaux se fait au travers d'une arborescence spécifique :
Méthode :
Créez un dossier submitted à la racine de l'arborescence
Créez deux sous dossiers eleve1 et eleve2 (autant que d'élèves créés en fait...)
Dans chaque sous dossier élève, copiez l'arborescence de votre devoir, donc dans notre exemple testPremier/DS1.ipynb
Complétez pour les deux élèves les fichiers DS1 avec des réponses. Par exemple eleve1 peut bien répondre et eleve2 va faire n'importe quoi ! Voici ce que je propose comme réponse pour chacun d'eux :
Exemple : eleve1
L'élève 1 complète la fonction isPrime, peut créer des nouvelles cellules pour tester son code, et clique sur le bouton Validate pour s'assurer qu'il passe les tests.
def isPrime(n):
L=1
if n in {2,3, 5, 7, 11, 13, 17, 19, 23, 29, 31}:
return True
elif n<=1 or n%2==0 or n%3==0 or n%5==0:
return False
else:
while L*L<n:
for inc in [6,4,2,4,2,4,6,2]:
L+=inc
if n%L==0:
return False
return True
Exemple : eleve2
L'élève 2 procède de même mais croit faire le malin en examinant les vérifications du professeur :) En apparence, la cellule de vérification s'exécute sans erreurs.
def isPrime(n):
return n in [5,17]
Mais il ne sait pas que le professeur à d'autre tests cachés :)
Les productions des élèves sont récupérées dans l'arborescence :
submitted
|_ eleve1
|_ testPremier
|_ DS1.ipynb
|_ eleve2
|_ testPremier
|_ DS1.ipynb
Complément :
La récupération des productions d'élèves est assurément la partie la plus fastidieuse de tout le processus. Néanmoins avec un peu de pratique des langages de script (bash par exemple), il est possible d'automatiser le dépôt des productions élèves dans l'arborescence. En effet, notre ENT nous fournit un zip contenant une arborescence un peu similaire avec un dossier du nom des élèves contenant le fichier à rendre.
Évaluer les réponses automatiquement
Vient le moment le plus agréable : la correction ! ! Retournez sur Formgrader, les 2 productions apparaissent dans la colonne Submissions
Cliquez sur le chiffre 2 pour voir les réponses.
En cliquant sur l'éclair vous déclencherez la correction pour l'élève. Néanmoins cela peut être fastidieux de le faire pour 24. Cela peut être automatisé en déployant la zone Instructions puis cliquant sur le lien command line pour faire apparaître une console. Il suffira juste de taper la commande indiquée pour corriger tous les élèves d'un coup !
nbgrader autograde "testPremier"
Fermez la console et revenez sur la page de soumissions : les élèves sont corrigés :)
eleve1 a eu 2/2 et eleve2 qui a cru faire le malin a eu 0/2 car son programme foireux n'a pas passé les tests cachés du professeur rusé :)
Personnaliser les évaluations
Un professeur consciencieux voudra tout de même regarder de près les soumissions de ses élèves ! Pour cela allez dans Formgrader puis cliquez sur le bouton Manual Grading. Cliquez sur le devoir DS1 :
Les copies sont anonymisées ! cliquez sur l’œil pour voir le nom de l'élève si vous voulez savoir !
Exemple : Correction de eleve1
Cliquez sur submission1 et saisissez des commentaires personnalisés. Vous pouvez également attribuer des points bonus.
Exemple : Correction de eleve 2
En cliquant sur le bouton Next-> en haut à droite, vous accédez à la copie de eleve2. On voit sur quel tests la fonction a échoué. L'élève ne mérite aucun points pour la méthode utilisée, on laisse la note à 0.
Complément :
Le bouton aide ( ?) en bas à droite donne des raccourcis clavier très pratiques sur cette page.