Archives par mot-clé : R

Mon royaume pour 4 Go de VRAM : faire entrer Ollama dans le GPU

Dans un précédent billet, « Mon royaume pour une IA en localhost », je racontais mes premiers pas avec Ollama. L’enjeu était assez simple : si je dois confier des articles, des rapports ou des archives de recherche à une intelligence artificielle, je préfère que tout cela reste dans ma machine. Garder l’IA dans sa boîte, donc, avec l’espoir de conserver un peu de prise sur ce que je lui donne et sur ce qu’elle en fait.

À ce stade, faire répondre un modèle dans un terminal avait quelque chose de presque magique. Mais entre demander un résumé de trois pages et faire analyser un véritable corpus de recherche, il y a un petit gouffre. C’est dans ce gouffre que mon ordinateur et moi sommes tombés.

L’histoire qui suit est donc un retour d’expérience sur la manière dont j’ai essayé de faire travailler Ollama avec une petite carte graphique de portable. Ce n’est pas un tutoriel universel : les réglages dépendent du modèle, du GPU, de sa mémoire et de la taille des textes. C’est plutôt un pense-bête documenté pour éviter de refaire, dans six mois, le même chemin à travers les journaux d’erreurs.

Le contexte : 839 documents et une semaine de patience

Je travaille sur les archives du projet Santé & Territoires au Sénégal. Le corpus rassemble des comptes rendus, présentations, termes de référence, tableaux, documents de travail et rapports produits autour des Living Labs de Mbane et de Keur Momar Sarr, près du lac de Guiers.

L’objectif n’était pas seulement de faire résumer les documents. Je voulais reconstruire une chronologie, retrouver les groupes impliqués, repérer les formes de participation, distinguer ce qui avait été proposé de ce qui avait réellement été fait et suivre la manière dont la perspective « Une seule santé » avait été progressivement prise en compte. Le tout en conservant, pour chaque codage, un extrait et un chemin vers le document source.

Après extraction des textes, agrégation des doublons et exclusion des images, vidéos et fichiers audio, il restait tout de même 839 unités documentaires susceptibles de passer devant le LLM.

J’ai donc lancé mon script R, assez fier de moi, avec plusieurs workers pour les opérations locales et Ollama pour le codage. Quelques heures plus tard, la barre de progression affichait quelque chose comme :

Codage LLM documents   16/839 | écoulé 4h29m | ETA ≈ 231h22m

Le script annonçait ensuite, avec un calme que je trouvais presque provocateur :

Timeout ou échec pour D00010 chunk 4 (4000 caractères) ;
repli en 2 sous-chunk(s) de 2500 caractères au maximum.

Le premier bloc attendait le timeout. Puis le script le découpait en deux et recommençait. Quand plusieurs requêtes partaient en même temps, elles se disputaient la mémoire disponible. À ce rythme, l’analyse ne ressemblait plus vraiment à un gain de temps. Elle ressemblait plutôt à une manière sophistiquée de transformer un ordinateur portable en radiateur et par ces temps de canicules, pas la meilleur idée que j’ai eu!

Pas qu’un problème de modèle

Ma première réaction a été de chercher un modèle plus petit. C’est assez logique : un modèle de 8 milliards de paramètres sera plus lourd qu’un modèle de 3 ou 4 milliards. Mais cela n’expliquait pas complètement pourquoi des passages de quelques milliers de caractères pouvaient immobiliser Ollama pendant plusieurs minutes.

La machine possède deux processeurs graphiques :

Intel Corporation Meteor Lake-P [Intel Arc Graphics]
NVIDIA RTX 500 Ada Generation Laptop GPU

La carte NVIDIA ne dispose que de 4 Go de VRAM. Ce n’est pas énorme, mais un llama3.2:latest quantifié pèse environ 2 Go. Il devait donc être possible d’en faire quelque chose.

La commande suivante confirmait d’ailleurs qu’Ollama voyait bien la carte :

nvidia-smi

Dans la liste des processus, /usr/local/bin/ollama occupait environ 666 Mio de mémoire vidéo. Mais cette information ne disait pas quelle part du modèle était réellement exécutée sur le GPU. Pour cela, il fallait demander directement à Ollama :

ollama run llama3.2:latest "Réponds uniquement par OK"
ollama ps

Et là, surprise :

NAME               SIZE     PROCESSOR          CONTEXT
llama3.2:latest    18 GB    71%/29% CPU/GPU    16384

Le modèle téléchargé faisait environ 2 Go, mais Ollama annonçait une empreinte de 18 Go et ne plaçait que 29 % du calcul sur le GPU. Le même test avec qwen3:4b-instruct donnait encore moins :

qwen3:4b-instruct    18 GB    83%/17% CPU/GPU    16384

Le GPU était donc bien utilisé, mais comme une petite annexe du CPU. La majeure partie de l’inférence se faisait toujours dans la mémoire centrale. Hors, j’ai toujour entendu Théo me parler de GPU dans sa thèse.

Quatre contextes pour une seule petite carte

L’indice principal était la valeur CONTEXT 16384. Ollama avait réservé beaucoup plus de mémoire que nécessaire. Le parallélisme était ici particulièrement coûteux : plusieurs requêtes simultanées signifient plusieurs contextes à conserver en mémoire. Quatre contextes de 4 096 tokens donnent justement 16 384 tokens à allouer.

La documentation d’Ollama précise que la mémoire nécessaire augmente avec le produit :

OLLAMA_NUM_PARALLEL × OLLAMA_CONTEXT_LENGTH

Sur une grosse carte, plusieurs requêtes parallèles peuvent augmenter le débit. Sur 4 Go de VRAM, elles font surtout sortir le modèle du GPU. Le paradoxe est assez joli : j’avais demandé plus de parallélisme pour aller plus vite, et ce parallélisme était précisément ce qui ralentissait le calcul.

Il fallait donc distinguer deux choses dans mon script :

  • les opérations de lecture, d’extraction et de classement des fichiers, qui peuvent utiliser plusieurs cœurs CPU ;
  • les appels au modèle, qui doivent rester séquentiels tant que la mémoire du GPU est aussi contrainte.

Dans R, je pouvais conserver dix travailleurs pour préparer les documents, mais il fallait impérativement revenir à :

--llm-workers 1

Régler Ollama plutôt que brutaliser R

Ollama fonctionne comme un service. Le script R lui envoie des requêtes HTTP, mais c’est Ollama qui décide où charger le modèle, combien de contextes préparer et combien de temps le garder en mémoire. Il n’y avait donc pas besoin d’ajouter du code CUDA dans R. Il fallait régler le serveur.

Sous Linux, cela passe par une surcharge du service systemd :

sudo systemctl edit ollama.service

J’ai commencé avec cette configuration :

[Service]
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_CONTEXT_LENGTH=6144"
Environment="OLLAMA_KEEP_ALIVE=30m"

Puis il faut recharger la configuration et redémarrer Ollama :

sudo systemctl daemon-reload
sudo systemctl restart ollama

Les paramètres ont chacun un rôle assez simple :

  • OLLAMA_NUM_PARALLEL=1 interdit à un même modèle de préparer plusieurs requêtes en parallèle ;
  • OLLAMA_MAX_LOADED_MODELS=1 évite que plusieurs modèles se disputent les 4 Go de VRAM ;
  • OLLAMA_CONTEXT_LENGTH fixe la quantité maximale de texte et de réponse que le modèle peut garder dans son contexte ;
  • OLLAMA_KEEP_ALIVE=30m évite de recharger le modèle entre deux documents, sans pour autant l’immobiliser éternellement dans la mémoire.

Avec un contexte de 6 144 tokens, llama3.2:latest tenait entièrement sur le GPU. J’ai ensuite tenté 8 192 tokens, parce que mon prompt contient à la fois un codebook, un schéma JSON, des métadonnées et plusieurs passages du document.

Le résultat restait très honorable :

NAME               SIZE      PROCESSOR         CONTEXT
llama3.2:latest    3.5 GB    9%/91% CPU/GPU    8192

Le modèle était désormais exécuté à 91 % sur le GPU, contre 29 % avant le réglage. On était passé d’une empreinte annoncée de 18 Go à 3,5 Go.

Gratter encore un peu de mémoire

À 8 192 tokens, la carte était juste à la limite. Il restait une possibilité : réduire la mémoire occupée par le cache K/V, c’est-à-dire la mémoire dans laquelle le modèle conserve les éléments du contexte déjà traités.

J’ai donc ajouté :

Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"

La configuration complète devient :

[Service]
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_KEEP_ALIVE=30m"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"

Flash Attention permet de réduire la consommation de mémoire lorsque le contexte augmente. La quantification q8_0 utilise environ deux fois moins de mémoire que le cache f16 par défaut, avec une perte de précision généralement faible. Il existe également un cache q4_0, encore plus compact, mais la perte devient plus sensible. Pour un travail de codage scientifique, je préfère réduire légèrement le contexte plutôt que comprimer davantage le cache.

Il faut ici éviter une confusion : je n’ai pas fine-tuné le modèle au sens de l’apprentissage automatique. Je n’ai modifié ni ses poids ni son comportement appris. J’ai plutôt ajusté — tuné, si l’on veut — son régime d’inférence : nombre de requêtes, taille du contexte, occupation de la mémoire et répartition entre CPU et GPU.

Faire moins de requêtes reste la meilleure optimisation

Même correctement installé sur le GPU, un LLM n’a aucune raison de lire 839 documents de bout en bout si la majorité n’est pas utile à la question de recherche. Le réglage matériel ne devait donc pas remplacer le travail méthodologique.

J’ai repris le script R pour organiser l’analyse en deux passes.

La première réalise une présélection à rappel élevé. Elle lit le nom, le chemin et quelques passages de chaque document, puis décide s’il peut documenter les Living Labs, la participation des parties prenantes ou la perspective « Une seule santé ». Les décisions sont exportées dans un fichier CSV et peuvent être corrigées manuellement.

Rscript analyse_corpus_llama31_8b.R \
  --input "ST_KB_destination" \
  --output "resultat_corpus_llama31" \
  --model "llama3.2:latest" \
  --triage-model "llama3.2:latest" \
  --mode triage \
  --triage-batch-size 8 \
  --workers 10 \
  --llm-workers 1 \
  --api-timeout 300

Le fichier 00_triage_decisions.csv possède une colonne manual_selected. Je peux y inscrire TRUE pour repêcher un document ou FALSE pour l’écarter avant la seconde passe.

La seconde passe ne lit plus nécessairement toutes les pages. Elle présente au modèle le début, la fin et les passages les plus denses en termes liés au terrain et aux catégories analytiques. Chaque observation doit rester associée à un extrait et au chemin de sa source.

Rscript analyse_corpus_llama31_8b.R \
  --input "ST_KB_destination" \
  --output "resultat_corpus_llama31" \
  --model "llama3.2:latest" \
  --triage-model "llama3.2:latest" \
  --mode full \
  --deep-reading targeted \
  --workers 10 \
  --llm-workers 1 \
  --api-timeout 300

La machine travaille donc mieux, mais elle travaille surtout moins inutilement. C’est probablement l’optimisation la plus importante de toute cette histoire.

Ce que j’en retiens

Faire fonctionner une IA en local ne consiste pas seulement à télécharger un modèle et à lancer une commande. Entre le modèle et la machine s’installe tout un petit monde de paramètres : quantification, contexte, cache, parallélisme, chargement des modèles et partage entre CPU et GPU.

Les valeurs par défaut sont nécessairement génériques. Elles ne savent pas que mon ordinateur possède une RTX 500 Ada de seulement 4 Go, que je préfère une requête fiable à quatre requêtes concurrentes, ni que mon corpus contient des centaines de documents en français avec un schéma de codage assez lourd.

Il faut donc reprendre la main sur l’outil. Pas pour optimiser chaque seconde comme un nouvel ergonome de soi-même, mais pour que la technique reste proportionnée à la machine et à l’usage. Dans mon cas, la frugalité ne consistait pas seulement à choisir un petit modèle. Elle consistait à limiter le parallélisme, choisir la taille de contexte utile, écarter les documents hors sujet et maintenir une possibilité de validation humaine.

Le modèle est moins gros, les requêtes sont moins nombreuses et le GPU est enfin devenu autre chose qu’un petit témoin lumineux dans nvidia-smi. Ce n’est toujours pas le futur. Mais, cette fois, ça ressemble un peu plus à un outil que je peux habiter.

Et de la philo ?

Cette expérience prend alors un autre relief à la lecture de Günther Anders, mon héro. Le « rêve des machines » n’est pas celui de mieux servir les humains, mais celui d’un monde entièrement organisé selon leur propre fonctionnement, dans lequel l’homme finit par devenir un rouage de l’appareil qu’il a construit. Le décalage prométhéen apparaît lorsque notre capacité à produire de tels dispositifs dépasse notre capacité à nous les représenter, à les maîtriser et à décider collectivement de leurs usages.

À une échelle évidemment bien modeste, mon premier réflexe avait précisément consisté à adapter mon travail aux exigences d’Ollama : multiplier les traitements, découper les documents, attendre des centaines d’heures et laisser la machine imposer son rythme à l’enquête.

Paramétrer le modèle, limiter les requêtes et sélectionner les textes pertinents pourrait peut être revenir à inverser cette relation : faire entrer la machine dans les contraintes de la recherche, plutôt que transformer le chercheur — et son corpus — en simples rouages de la machine.

Quelques commandes à garder sous le coude

Identifier les cartes graphiques :

lspci | grep -Ei "VGA|3D|Display"

Surveiller la carte NVIDIA :

watch -n 1 nvidia-smi

Vérifier où Ollama a chargé le modèle :

ollama ps

Afficher la configuration transmise au service :

systemctl show ollama --property=Environment

Arrêter un modèle et libérer sa mémoire :

ollama stop llama3.2:latest

Quelques références

Institutional Gramar – un outils pour penser la gestions des ressources

Du 19 au 24 juin 2023, j’ai pu participer au congrès de l’IASC (International Association for the Study of the Commons) qui s’est déroulé à Nairobi. La thématique de la conférence était « the commons we want« , a donné lieu à une très grande diversité de panels en parallèle et donc a un programme riche et varié.

J’ai eu la chance, presque un peu par hasard, de participer au workshop, puis au panel sur l’Institutional Gramar (IG) proposé par Saba Siddiki, Christopher Frantz, et Ute Brady. Ce qui m’a permis une introduction rapide aux potentialités de la formalisation proposée.

Une synthèse de l’institutional Grammar

L’approche de la Grammaire institutionnelle (Institutional Grammar ou IG en anglais) est une approche définie conceptuellement par Crawford et Ostrom en 1995. Au fil des 25 dernières années, cette approche a été largement utilisée dans l’analyse des politiques, la modélisation informatique, etc.

l’IG appelée « Institutional Grammar 2.0 », actualise l’approche pour de nouvelles applications dans divers domaines de recherche. Cette version 2.0 offre une représentation plus précise et complète des informations institutionnelles, en mettant l’accent sur le sens, les fonctions et les effets des déclarations institutionnelles.

La formalisation des informations en passant par un encodage particulier et non ambigu (ou en tout cas moins ambigu que le langage naturel), indépendamment du domaine d’application et de la méthode analytique utilisée, ouvre des perspectives extrêmement intéressantes et déjà largement utilisées en termes d’analyse comparée et d’évolution temporelle des organisations. En soulignant l’importance de l’analyse institutionnelle, il me semble que l’IG est adaptable à diverses situations d’actions.

La formalisation proposée par l’IG 2.0 repose sur une grammaire générative décrite dans la table ci dessous par Watkins et Westphal (2016).

Tableau reprenant les composants de l’IG dans le papier de Watkins et Westphal (2016)

L’intérêt de l’Institutional Grammar réside pour moi dans le cadre d’analyse rigoureux qu’elle offre et qui donne des outils holistiques pour étudier le fonctionnement des institutions et des organisations. En utilisant cette approche, les chercheurs peuvent mieux comprendre comment les règles, les normes et les valeurs institutionnelles influencent les comportements et les décisions des acteurs impliqués.

Cette compréhension approfondie des structures institutionnelles et de leurs effets permet de proposer des solutions plus adaptées pour résoudre les problèmes et les défis auxquels sont confrontées les organisations. L’Institutional Grammar peut également aider à identifier les facteurs qui favorisent ou entravent l’efficacité des institutions, ce qui peut avoir des implications importantes pour l’amélioration des politiques publiques et des pratiques organisationnelles.

De retour dans la vraie vie, j’ai essayé de comprendre plus finement la méthodologie et les usages que je pouvais en faire. J’ai identifier deux cas d’usage au Sénégal : autour du lac de Guiers dans le cadre du projet Santés & Territoires, et dans la zone pastorale dans le cadre du projet Dundi Ferlo, et dans le cadre de la convention de programme sur les Communs.

Santés & Territoires : une approche co-construite de one Health

Le projet s’appuie sur une approche participative, impliquant les acteurs du système autour de la transition agro-écologique comme levier d’amélioration des santés (approche one Health). Des chercheurs et des acteurs locaux sont donc impliqués dans 4 pays : au Sénégal, au Bénin, au Laos et au Cambodge, au travers de dispositifs de recherche-action que peuvent être les livings lab. Au Sénégal, les livings-lab se positionnent autour du lac de Guiers (à Mbane, et Keur Momar Sarr).

Entre février et septembre 2023, Amandine Adamczewski-Hertzog et moi avons encadré Mathilde Hibon dans le cadre de son stage de fin d’études pour un double diplôme entre l’école d’agronomie de Purpan et l’ISARA (Norwegian University of Life Sciences, vous pouvez retrouver son rapport ici).

Mathilde put encoder tous ses entretiens avec l’IG. Cela lui a donné 150 entrées dans sa base. À partir de là, on a exploré ces entrées avec des outils de l’analyse de réseau (R, et gephi). En les exprimant par point de vue. C’est à dire, envisager la manière dont chacun considère les relations d’interaction (au travers de règles ou de stratégies). Voilà le résultat de l’une de ces analyses du point de vue des populations locales.

En regardant les relations qui sont identifiées à partir des entretiens mener auprès des institutions, on constate que la centralité des acteurs n’est pas du tout la même, ce qui permet entre autres choses de visualiser facilement les différences de points de vue.

La CP Commun

Dans le cadre de la CP Commun, l’équipe GIREL du GRET Sénégal a séléctionné deux terrain : Mont-Rolland et Diender pour y déployer le jeu f’eau diem. Le jeu f’eau diem étant utilisé comme une arène qui permet de virtualiser les problèmes auxquels les participants font face. On réutilise à notre compte le concept de Johan Huizinga (1949) : “The Magic Circle”. Cela renvoie à l’espace conceptuel (mental) et physique (le lieu) dans lequel les règles du jeu prennent le dessus sur celles de la réalité quotidienne. L’identification de cet espace permet aux observateurs de la session de jeu de mieux comprendre les relations que les joueurs tissent localement avec la réalité. Comment ceux-ci adoptent des rôles ou des comportements qu’ils n’auraient pas dans leur vie quotidienne.

Les participants a la session de jeu f’eau diem de Diender en mai 2024

De cette manière nous nous attendons à ce que les joueurs ne nous parlent pas directement de leurs problèmes et de solutions de gestion mais de ceux identifiés dans le jeu, qui pour autant ont des équivalences dans la réalité.

A partir des observations des sessions de jeux, l’objectif est de remplir la matrice des formalisations des règles largement inspirées de l’Institutional gramar. Ce formalisme nous semblait être en mesure de capturer les éléments de réglementation formelle ou informelle que les participants allaient évoquer dans le cercle magique (c.f. fig I).

Figure issue du papier de Schlüter, A., & Theesfeld, I. (2010). The grammar of institutions: The challenge of distinguishing between strategies, norms, and rules. Rationality and Society p. 457

Les institutions (action d’instituer en économie) sont composées d’un ensemble de stratégies, normes et règles qui sont mises en place par un groupe d’agents. Pour un agent, une institution peut-être consciente et inconsciente. La Stratégie décrit le comportement d’un joueur dans un jeu. Elle peut être individuelle si on ne sait pas qui d’autre la mobilise. Collective, dans ce cas là, on assiste à l’apparition d’une institution. Les normes peuvent être internalisées, c’est-à-dire incorporées à l’intérieur de l’individu de manière à ce qu’il s’y conforme sans récompense ou punition externe, ou elles peuvent être imposées par des sanctions positives ou négatives venant de l’extérieur.

Les règles identifiées par les observateurs devaient être mises en discussion puis testées dans des sessions de jeux. S’il y a eu des adaptations locales, on peut globalement dire que le plan ne s’est pas passé comme prévu. Philippe Karpe (Cirad – UMR SENS) nous avait un peu mis en garde vis-a-vis de la grille. Elle était très compatible avec le droit positif, mais assez peu opérante pour faire face aux systèmes de régulation endogène mis en place par les participants. On a donc encore du travail 🙂

Dundi Ferlo : travailler avec les populations locales au projet de Grande Muraille Verte

Penda Diop Diallo, a emmené le CNRF (Centre National de Recherche Forestière Sénégalais) dans les approches de modélisation d’accompagnement (ComMod). Dans ce projet il s’agira de s’inscrire dans le projet panafricain de la grande muraille verte, en prenant en accompagnant les acteurs dans le processus. Dans les faits, cela veut dire accompagner la mise en place de parcelles de reboisement gérer collectivement par les populations locales aussi bien du point de vue du fourrage herbacé, que du potentiel fourrage aérien, et un jour des productions forestières non ligneuses.

Dans le cadre de ce travail, Penda accompagnée d’Anna Ndiaye ont réutilisé et adapté un jeu sérieux dans la plus pure approche ComMod. Il s’agissait de se servir de cet outil comme d’un simulateur social qui permettent aux acteurs de se projeter dans des mesures de gestion, d’en évaluer ainsi la faisabilité et les implications sur l’usage de la ressource.

Ces activités, réalisées à Vélingara Ferlo et Younofere, ont amené les acteurs à exprimer des ensembles de règles de gestion qui ont été implémentés la même année dans les parcelles. Penda a travaillé à la formalisation de ces règles dans l’Institutional Grammar pour pouvoir identifier les trajectoires institutionnelles que chacune des zones a décidé de prendre. Cela permettra de comparer facilement les directions que vont prendre les deux terrains d’étude.

Les perspectives

Si ça vous intéresse je vous encourage à aller voir le site de l’institutional Grammar initiative. En terme de perspective, il me semble que ce cadre est extrêmement stimulant, malgré les limites identifié précédemment, pour modéliser et donc simplifier les types de relation liés aux règles formelles et informelles dans la zone.

Traiter des images MODIS avec R pour calculer un NDVI

La Nasa propose depuis 1999 des images MODIS (Moderate-Resolution Imaging Spectroradiometer) à différentes résolutions spatiales et temporelles. Elles sont produites par deux satellites en orbite, Terra (1999) et Aqua  (2002), qui embarquent des capteurs pour le programme Earth Observing system.

Les instruments permettent d’enregistrer 36 bandes spectrales avec une fréquence de passage de 1 à 2 jours. La résolution des images diffère selon les bandes enregistrées et varie entre 0.25 et 1 km. Nous parlions il y a quelques jours du site reverb|echo de la Nasa, il se trouve qu’un certain nombre d’images sont disponibles sur le site.

Quelles données ?

Mais pour ça il faut savoir ce qu’on cherche, et la nomenclature des produits n’est pas vraiment transparente [1].  À titre d’exemple :

  • MOD9Q1 – Surface Reflectance 8-Day L3 Global 250m
  • MOD13Q1 – Vegetation Indices 16-Day L3 Global 250m
  • MOD11A2 – Land Surface Temperature/Emissivity 8-Day L3 Global 1km

Une fois qu’on en sait un peu plus sur le type de produit que l’on veut utiliser, il va falloir le télécharger et le traiter. Dans un post précédent, j’expliquais comment configurer sa machine pour utiliser wget. Si vous optez pour cette solution, il vous faudra utiliser le MRT pour reprojeter et assembler vos images. L’interface est assez intuitive et on peut faire du traitement de masse.

Mais je suis tombé aussi ce matin sur les logs de release d’un package R que je me suis empressé de tester : MODIStsp. Si vous avez déjà regardé MRT, MODISStsp n’est qu’un moyen de rester dans R pour télécharger les images. On pourra aussi regarder du côté du package MODIS qui lui n’intègre pas d’interface graphique.

Bon mais on parlait de NDVI dans le titre !

Traiter les images NDVI : MOD13Q1

En cherchant comment traiter les images MODIS, je suis tombé sur des ressources intéressantes. Notamment une page qui vous prend par la main pour traiter les données MODIS (MOD13Q1) dans R[2]. Je vous propose donc de faire un petit point pas à pas !

J’ai téléchargé et projeté les données grâce au package MODISStsp. J’ai donc un dossier qui contient les fichiers hrf, mais aussi un autre qui contient les fichiers tiff produits par le package.

Or quand on ouvre les données (dans Qgis), les gammes de valeurs ne correspondent pas à celles attendues pour du NDVI! On devrait avoir des valeurs entre -1 et 1 !

 

Freq. pour la tuille 16 – 17/01/2016

Il va falloir retravailler le raster pour obtenir les bonnes valeurs . Heureusement « the office of outer space affaire » nous donne la marche à suivre dans R[3]. Je vous propose donc ici un script commenté et customisé pour l’occasion.

library(raster)  
library(sp)
library(doParallel)
library(rgdal)
library(magrittr)

rm(list = ls()) ##clear env.

#create stack from tif NDVI files
path.v = "~/Documents/futurSahel/MOD13Q1_TS/VI_16Days_250m_v6/NDVI/"
l.files = list.files(path.v, pattern = ".tif")


my.stack = stack(paste0(path.v,l.files)) ##create raster stack of files in a directory
# load borders
border = shapefile("~/Documents/futurSahel/Senegal_gadm.org/SEN_adm0.shp") #ToDo: insert link to the shapefile with the country borders


## We use doParallel and magrittr packages to pipe different actions (crop and mask)
registerDoParallel(6) #we will use 6 parrallel thread
result = foreach(i = 1:dim(my.stack)[3],.packages='raster',.inorder=T) %dopar% {
  my.stack[[i]] %>% 
    crop(border) %>%
    mask(border)
}
endCluster()
ndvi.stack = stack(result)

ndvi.stack = ndvi.stack*0.0001 #rescaling of MODIS data
ndvi.stack[ndvi.stack ==-0.3]=NA #Fill value(-0,3) in NA
ndvi.stack[ndvi.stack<(-0.2)]=NA # as valid range is -0.2 -1 , all values smaller than -0,2 are masked out
names(ndvi.stack) = seq.POSIXt(from = ISOdate(2016,1,17), by = "16 day", length.out = 23) # atribut name as date for each layer

my_palette = colorRampPalette(c("red", "yellow", "lightgreen")) #Create a color palette for our values
## Plot X maps in the same layout
spplot(ndvi.stack, layout=c(4, 6),
       col.regions = my_palette(16))

Ce qui nous donne pour les 23 pas de temps étudiés l’image suivante. On voit bien reverdir la partie supérieure de la carte entre juillet et octobre en 2016.

Indice NDVI à partir des données MODIS MOD13Q1 sur le Sénégal pour 2016

Pour avoir un ordre d’idée, traiter 23 images et produire le graphe, en parallélisant une partie, me prend 11 min .

Des ressources :

[1]Type d’images disponible : https://modis.gsfc.nasa.gov/data/dataprod/

[2]http://www.un-spider.org/advisory-support/recommended-practices/recommended-practice-drought-monitoring/step-by-step/R

[3]http://www.un-spider.org/sites/default/files/Skript%20VCI%20final.R

GRASS-GIS 7 et R

Contexte

Avec @fabio_zottele, nous nous sommes replongés ce weekend sur un travail un peu vieux. Celui-ci remonte à 5 ans, et consiste à proposer un algorithme basé sur des librairies/logiciels libres afin de détecter les terrasses viticoles. Ce travail avait initialement été développé sur R gdal et grass 6.3. pour une petite zone de la val di Cembra.

Notre objectif est aujourd’hui de systématiser l’algorithme et de vérifier que l’évolution des technologies et des algorithmes sur lesquels nous nous étions basés produit toujours le résultat attendu.

Installation de GRASS7Grass-GIS

La première chose à faire est de compiler GRASS-GIS en version 7, car les dépôts ne sont pas encore à jour sur Fedora. Vous pouvez trouver toute la documentation sur le wiki de grass.

On pourra commencer par télécharger le weekly snapshot du projet , et installer les dépendances qui vont bien :

sudo dnf install gcc gcc-c++ bison flex ncurses-devel proj-epsg proj-nad xml2 \
proj-devel gdal gdal-devel gdal-python sqlite-devel mesa-libGL-devel \
fftw-devel mesa-libGLU-devel libXmu-devel libX11-devel geos geos-devel \
libtiff-devel lesstif-devel python-devel numpy wxPython wxGTK-devel \
python-dateutil python-imaging python-matplotlib-wx subversion doxygen python-sphinx \
netcdf-devel postgresql-devel lapack lapack-devel blas blas-devel atlas atlas-devel

On peut ensuite aller compiler les sources :

cd ~/Téléchargement/grass7.0.svn/
./configure \
  --with-cxx \
  --with-gdal=/usr/bin/gdal-config \
  --with-proj --with-proj-share=/usr/share/proj \
  --with-python=/usr/bin/python-config \
  --with-geos \
  --with-sqlite \
  --with-nls \
  --with-wxwidgets=/usr/bin/wx-config \
  --with-fftw \
  --with-cairo --with-cairo-ldflags=-lfontconfig \
  --with-freetype --with-freetype-includes=/usr/include/freetype2 \
  --enable-largefile \
  --without-odbc \
  --with-ffmpeg \
  --with-ffmpeg-includes="/usr/include/ffmpeg /usr/include/ffmpeg/libav* /usr/include/ffmpeg/libpostproc /usr/include/ffmpeg/libswscale" \
  --with-blas --with-blas-includes=/usr/include/atlas-x86_64-base/ \
  --with-lapack --with-lapack-includes=/usr/include/atlas-x86_64-base/ \
make -j4 #pour compiler sur 4 thread
sudo make install

Et nous voilà avec une belle installation de grass7. Je vous encourage à faire un tour du propriétaire parce qu’un travail formidable a été fait ! Bravo à l’équipe de dev!

Comment se passe la communication avec R ?

RlogoEt bien figurez-vous qu’il y a le package qui va bien 😀 : rgrass7 qui s’installe comme d’habitude dans R avec :

install.packages(« rgrass7 », dependences = TRUE)

Mais l’utilisation diffère un peu de son grand frère. En effet, on peut désormais spécifier l’emplacement de votre GRASS7 fraichement compilé. On procèdera donc de la manière suivante :

remove(list=ls())
## Configuration Parametrs:
gisBaseLocation = "/opt/grass" #where the GRASS executables are
library(rgrass7) #load lib in R
initGRASS(gisBase=gisBaseLocation, override=TRUE) #Run GRASS in & Cancel previous running GRASS instance in R

L’exécution se fait ensuite avec une seule et même commande R à laquelle on passera en paramètre la commande GRASS

execGRASS(cmd= "g.remove", flags=c("f", "b"), parameters= list(type="raster", pattern="*"))

Ici on exécute donc dans R une commande GRASS qui va permettre de supprimer tous les rasters de la base de données GRASS.

Pour prendre un autre exemple :

execGRASS(cmd= "r.param.scale", flags= c("overwrite", "verbose"), parameters= list(input="DTM",output="CURVATURE", size=5, method="profc", zscale=2.0))

Ici on exécutera la commande r.param.scale  en spécifiant toutes les options.

Quand on veut ensuite sortir les résultats de GRASS pour les manipuler dans R, la méthode n’a pas beaucoup changé :

param.scale = raster(readRAST("CURVATURE"))

Ici on utilise la fonction raster du package éponyme pour convertir en raster les données en sortie de la fonction readRAST du package rgrass7.

Pour le plaisir des yeux

Voilà donc à partir de données LIDAR à 1m la proportion de surface avec des terrasses à l’échelle tu Trentino !

mappaEroica
Proportion de surfaces agricoles terrassées par tuile de données LIDAR à l’échelle de la région Trentino

Les coopératives viticoles en France

Grâce au blog de R. Schirmer, j’ai découvert au début de l’été le site de l’observatoire de la viticulture française. Ce site permet d’avoir accès à une documentation très fournie (chiffres à la clef) sur des sujet aussi variés que :

  • les surfaces plantées en vigne
  • les surfaces par cépage dominant
  • les volumes vinifiés par les coopératives ou les caves particulières par commune
  • etc.

Comme je suis en plein travail sur le poids du système coopératif sur le cru Banyuls (dans les PO), j’ai regardé les données auxquelles je pouvais accéder sur le site de l’observatoire. J’ai été enchanté de découvrir dans la rubrique vinification des données diachroniques (entre 2007 et 2013) sur les quantités totales livrées aux coopératives ou vignifiées par des caves particulières, mais aussi type de vin (AOP rouge/rosé, AOP blanc, IGP rouge/rosé, IGP blanc, et sans IGP).

Une véritable mine d’or donc ! Hier soir, prenant mon courage à bras le corps, je me suis lancé dans la récupération des données, et ce sur plusieurs années (2010 et 2013). Un travail long et fastidieux (qui aurait pu être simplifié si les possibilités de téléchargement des données avait été optimisées, mais bon quand on veut, on peut !).

Voilà donc les deux premières sorties graphiques :

  • ggplot_coop_2010_203Sur ces deux premières cartes on peut essayer de jouer au jeu des 7 erreurs :
  • Les bouches ont légèrement reculé
  • Le Haut-Rhin et le  Bas-Rhin sont entrés en course avec des volumes non négligeables
  • Les volumes ont un peu augmenté dans les Pyrénées orientales

Si ensuite on s’intéresse à l’évolution des volumes apportés aux coopératives et vinifiés par des caves particulières entre 2010 et 2013, on produit alors les cartes suivantes :

ggplot_variation_2010_203La première chose qu’on peut noter est la différence d’ordre de grandeur entre les volumes gagnés (ou perdus) par les caves coopératives et ceux générés par les caves particulières. On peut observer deux petites choses. Les volumes produits aussi bien par les coopératives que par les caves particulières entre 2010 et 2013 sont en réduction en Gironde et en augmentation pour le département de l’Hérault. La progression semble également positive pour les départements du Bas Rhin et du Haut Rhin.

Vous pouvez retrouver le matériel et la méthode sur github

Ampélographie et cépages mondiaux : morceaux choisis de géographie viticole

Genèse

J’essaie de reconstruire petit à petit sur les ruines de l’ancien blog, réutiliser une belle pierre pour en faire un appui de fenêtre, et essayer de conserver une trace des travaux qui ne servent à rien, mais qui me tiennent à cœur malgré tout.

Je me suis donc lancé ce soir sur les traces d’un vieux billet perdu à tout jamais (même sur archive.org). Un billet qui avait commencé sur un air de défi pour moi suite à une belle news de portail SIG.

En janvier 2014 donc Francois-Nicolas ROBINNE publiait un petit article pour signaler l’existence d’une base de données construite et mise à disposition par l’université d’Adélaïde, en Australie.

Cette base de données reprend, par pays les surfaces plantées pour 1200 cépages (connus et moins connus). Or, quand on parle d’informations et de pays, un géographe a envie de faire des cartes. En prenant au mot la remarque François-Nicolas je vous propose donc quelques cartes des cépages mondiaux et moins mondiaux…

Morceaux choisis de géographie viticole

La Douce Noire (le Corbeau)

répartition de la Douce Noire dans le monde en 2010
Répartition de la Douce Noire dans le monde en 2010

La douce noire (le nom que lui préfèrent les Savoyards) aussi appelée corbeau (dans les registres officiels), a été réautorisée à la culture dans toute la France en 2009 . C’est un raisin de cuve noir, qui était jadis largement cultivé dans le massif du mont Blanc (connu en Italie sous le nom Dolcetto negro). Comme on le voit sur la carte, il est largement cultivé en Argentine, mais commence à être réintroduit en France grâce aux efforts du Centre d’Ampélographie Alpine (et particulièrement R. Raffin et M. Grisard). Il est particulièrement intéressant en ces temps de changement climatique, car il produit un vin peu alcooleux. En Savoie, il était généralement mélangé dans les parcelles avec du Persan et de la Mondeuse qui sont deux cépages de seconde époque (ce qui permet une vendange simultanée).

Selon l’inventaire des cépages de 1957 que j’avais étudié et cartographié pendant un stage au Centre d’Ampélographie Alpine il en restait 499ha en Savoie.

Le Gewurztraminer (ou traminer aromatico)

répartition du Gewurztraminer a travers le monde
répartition du Gewurztraminer à travers le monde

Le 2nd cépage sur lequel je voudrais m’arrêter est le Gewurztraminer ou Traminer aromatico pour les Italiens. Car si ce cépage est bien connu en France en particulier à cause de l’AOC alsacienne, c’est à nos voisins italiens que je dois l’une des plus belles réussites. Je travaille dans la vraie vie avec la fondazion E.Mach dans le Trentino en Italie. Et il se trouve qu’on cultive très largement le Traminer aromatico dans cette région. Pour les besoins de ma thèse j’ai donc fait quelques séjours prolongés. Le contexte du Val Di Cembra ou de l’Alto Adige sont particulièrement propices à ce cépage rose.

Si d’autres cépages vous intéressent, les scripts R et les (82) cartes sont sur github. Vous pouvez jouer avec les scripts et si, comme L. Jegou, vous voulez éviter cet horrible mercator, vous pouvez forker et jouer avec la fonction coord_map() de ggplot2 (Attention les surprises! la simplification de polygones a été fait avec les pieds)

Terroir congress, 2014, Tokaj, Hungary

Du 7 au 10 juillet 2014 s’est déroulé en Hongrie le bien connu (dans le milieu autorisé) congrès terroir. Cet évènement a regroupé, comme tous les deux ans, près de 200 chercheurs du monde entier pendant quelques jours dans la petite ville hongroise de Tokaj, pour échanger autour de cette notion (ô combien complexe) du terroir.

Les échanges que j’ai eu lors de ce congrès m’ont donné envie, une fois de retour en France, de revisiter les données produites par mon petit script qui moissonne, depuis plusieurs mois, les tweets parlant de terroir.

L’information d’un découpage mondial ?

Je ne reviendrai pas sur la procédure que j’ai déjà expliquée dans un article de geotribu. J’ai effectué une classification univariée des résultats par pays pour essayer de me faire une idée de l’internationalisation du terme.

classificationAvec une classification automatique de jenks sur 5 classes, voilà les résultats. On constate qu’une très grande majorité des pays ne parle pas de « terroir »… Et au final parmi ceux qui en parlent, on peut constater de grands écarts entre les pays.

map_twitterSur cette carte (dans une projection funky (mapproj: gilbert)), on observe tout de suite que la notion de terroir est plutôt un terme utilisé par les « vieux » pays producteurs, mais pas seulement. C’est sans doute une question d’adoption du langage. En effet, les États-Unis sont dans la classe qui mobilise le plus d’utilisation (entre 21 et 34 % des tweets avec le mot « terroir ») et la France est juste derrière dans la classe 16 à 21%.

Les autres pays producteurs de vin en Europe (en particulier l’Italie et l’Espagne) sont plus loin derrière et partagent la même classe que les pays d’Amérique latine (entre 1 et 5% des tweets).

Échelle géographique nationale ?

On s’interroge ensuite tout naturellement sur la pertinence de raisonner à l’échelle nationale, et ainsi donner autant de points aux USA qu’à un pays européen. Il faut donc trouver un moyen de s’abstraire des limites géographiques.

L’exercice n’est pas trop compliqué dans la mesure où la donnée que nous récoltons est sous forme de points géoréférencés. La question reste l’échelle d’agrégation pour garder du sens. map_twitter_hexa

Avec cette agrégation par hexagones, on peut voir qu’il y a des inégalités spatiales dans l’utilisation du mot « terroir », et cela au sein même d’un territoire national ! Pour garder l’exemple des États-Unis, le centre du pays disparaît au profit des côtes Est et Ouest qui représentent de véritables « hotSpots » de l’utilisation du mot.

On pourrait rapprocher l’utilisation de ce mot aux zones urbaines (avec en Europe, un beau Hotspot parisien), ce qui représenterait un beau paradoxe. Peut-être parlons-nous volontiers de terroir dans un bar à vin parisien que sur les terrains viticoles de Bourgogne ou d’ailleurs :-)!

Sur ce, je vous laisse avec en prime de petites images des visites de terrain sur le vignoble de Tokaj.

 Des visites de terrain

Disznoko winnery

Une winnery historique où j’ai découvert le tokaj aszu, un vin produit à partir d’une double vinification. Des raisins botrytisés d’un côté et une vinification plus traditionnelle de l’autre. Les deux sont mélangés pendant quelques jours pour que les arômes des aszu passent dans le liquide et lui donnent des notes d’abricot, tintées de menthe !

L’occasion également de déguster un tokaj eszencia… essence même des raisin aszu récoltéd par gravité !

la cave de disznoko
La cave de disznoko

disznoko-celar
Dans les galeries de Disznoko

Nobilis winnery

DCIM102GOPRO
Dans la cave du domaine Nobilis

Un domaine familial de moins de 15ha d’où sortent des vins de tokaj fabuleux, dommage qu’ils soient compliqués à trouver en France … avis aux cavistes. Il y a quelque chose à faire ici :-). Une dégustation verticale, des comparaisons de millésimes surprenants !

PS : Pour ceux que ça intéresse, vous pouvez retrouver la présentation ( disponible sur gitHub) que j’ai faite lors de l’introduction à la session 4 du congrès. Il s’agissait de ré-explorer la pensée de Roger Dion par l’intermédiaire des SMA.