Les posteurs les plus actifs de la semaine
Aucun utilisateur |
Sujets les plus vus
Les boucles sont déconseillées dans R ?
5 participants
Page 1 sur 1
Les boucles sont déconseillées dans R ?
Bonjour,
J'en ai fait les frais lors de simulations, d'avoir un temps de calcul assez long en utilisant des boucles sous R, notamment les boucles "for".
Quel est la méthode optimale pour lancer des itérations sous R ?
Utiliser apply, sapply, lapply ou bien il existe d'autres méthodes ?
Merci d'avance
J'en ai fait les frais lors de simulations, d'avoir un temps de calcul assez long en utilisant des boucles sous R, notamment les boucles "for".
Quel est la méthode optimale pour lancer des itérations sous R ?
Utiliser apply, sapply, lapply ou bien il existe d'autres méthodes ?
Merci d'avance
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Il faut au maximum utiliser la structure vectorielle des données de R.
Dans un exemple simple, si je veux multiplier tout les éléments d'un vecteur x par 2, je peux faire ça avec une boucle, ou bien juste taper 2*x, etc.
On peut également, en cas de nécessiter, utiliser la fonction compile() du package compiler, qui réduit pas mal les temps de calculs, notamment dans des simulations. Je l'utilise fréquemment.
Enfin, la solution que je préfère, est de coder la simulation en C, et d'intégrer le code C compilé dans R, avec la fonction .C(). Ca demande un peu de pratique, mais c'est clairement la solution la plus rapide pour faire de la simulation, et ça offre d'un coup tout les outils statistiques et graphiques de R (par exemple pour analyser les résultats), ce qui est vraiment appréciable.
HTH, Eric.
Dans un exemple simple, si je veux multiplier tout les éléments d'un vecteur x par 2, je peux faire ça avec une boucle, ou bien juste taper 2*x, etc.
On peut également, en cas de nécessiter, utiliser la fonction compile() du package compiler, qui réduit pas mal les temps de calculs, notamment dans des simulations. Je l'utilise fréquemment.
Enfin, la solution que je préfère, est de coder la simulation en C, et d'intégrer le code C compilé dans R, avec la fonction .C(). Ca demande un peu de pratique, mais c'est clairement la solution la plus rapide pour faire de la simulation, et ça offre d'un coup tout les outils statistiques et graphiques de R (par exemple pour analyser les résultats), ce qui est vraiment appréciable.
HTH, Eric.
Eric Wajnberg- Nombre de messages : 1238
Date d'inscription : 14/09/2012
Re: Les boucles sont déconseillées dans R ?
Je suis d'accord avec Eric. Si toutefois tu n'as pas envie de programmer en C, la fonction apply permet deja de gagner enormement de temps. Une autre solution et de lancer tes simulations en parallele (package parallel), mais la encore, ca demande un peu plus de maitrise.
Ayana
Ayana
Ayana- Nombre de messages : 550
Localisation : Londres
Date d'inscription : 18/08/2009
Re: Les boucles sont déconseillées dans R ?
Salut,
Cette discussion a eu lieu sur toutes les plates-formes d'entraide sur R et la réponse n'est jamais directe. Tu peux parfaitement avoir une boucle plus efficace qu'un apply.
Donc la première chose à faire si tu veux faire de l'optimisation est de screener ton code pour identifier les sources de lenteurs. Certains types d'objets sont à éviter (les listes par exemple et donc les data.frames). Des pratiques sont à proscrire comme construire la sortie au fur et à mesure des itérations: il vaut mieux, quand c'est possible, générer ta sortie dans un objet vide mais avec la structure complète et le remplir avec les itérations de la boucle. Il y a énormément de choses à faire (la vectorisation déjà citée par Eric est une très bonne clef d'optimisation) avant de se lancer dans de la programmation C (ou Python ou Julia ou....) ou le calcul parallèle.
Il en reste pas moins que les solutions C ou calcul parallèle sont diablement efficace ! Petit rappel au passage et sauf si j'ai loupé une actu là dessus à un moment, R utilise un seul processeur son fonctionnement de base. Donc si tu as un processeur à plusieurs coeurs, tu as des capacités limitées de calcul dans R.
HTH
Cette discussion a eu lieu sur toutes les plates-formes d'entraide sur R et la réponse n'est jamais directe. Tu peux parfaitement avoir une boucle plus efficace qu'un apply.
Donc la première chose à faire si tu veux faire de l'optimisation est de screener ton code pour identifier les sources de lenteurs. Certains types d'objets sont à éviter (les listes par exemple et donc les data.frames). Des pratiques sont à proscrire comme construire la sortie au fur et à mesure des itérations: il vaut mieux, quand c'est possible, générer ta sortie dans un objet vide mais avec la structure complète et le remplir avec les itérations de la boucle. Il y a énormément de choses à faire (la vectorisation déjà citée par Eric est une très bonne clef d'optimisation) avant de se lancer dans de la programmation C (ou Python ou Julia ou....) ou le calcul parallèle.
Il en reste pas moins que les solutions C ou calcul parallèle sont diablement efficace ! Petit rappel au passage et sauf si j'ai loupé une actu là dessus à un moment, R utilise un seul processeur son fonctionnement de base. Donc si tu as un processeur à plusieurs coeurs, tu as des capacités limitées de calcul dans R.
HTH
Nik- Nombre de messages : 1606
Date d'inscription : 23/05/2008
Re: Les boucles sont déconseillées dans R ?
Bonjour,
Dans la famille des apply, très souvent c'est le vapply le plus rapide. La fonction apply étant la plus lente de sa famille (pour travailler sur un data.frame, un array ou une matrice). Après les fonctions apply and co ne sont que des alias qui renvoient vers des boucles ... via des fonctions compilées. Très souvent la boucle est plus lente que ces fonctions parce que mal programmée. Un exemple, le calcul de la moyenne des colonnes d'un tableau de 1000 * 1000 :
Après je partage (en partie) l'avis de Nik. La question des boucles est récurrente et dépend du contexte et de ce que l'on souhaite faire.
La chose certaine à éviter ce sont les boucles emboitées. Plusieurs boucles les unes dans les autres et c'est vite la catastrophe. Mais pour éviter ça on peut générer l'ensemble des combinaisons i, j, k, ... dans un data.frame via expand.grid et ne faire qu'une boucle sur les lignes de ce data.frame par exemple.
Ce qui semble important de faire aussi avec les boucles dans les dernières version de R qui utilisent la compilation Just In Time par défaut (fonction enableJIT du package compiler), c'est des les "encapsuler" dans une fonction, pour que cette dernière soit compilée et que le calcul aille plus vite (voir précédent exemple). Je ne suis pas réellement arrivé à savoir si les boucles étaient elles aussi compiler (tous mes tests en ce sens ne se sont pas révélés concluants).
De manière générale, Nik à raison il te faut identifier via du profiling les sources de lenteur de ton code, voir si tu ne peux pas les programmer autrement en les vectorisant par exemple. L'autre chose est aussi de sortir de la boucle toutes les opérations qui peuvent ne se faire qu'une seule fois. Par exemple si à chaque itération tu divises un résultat par 1000, alors il vaut mieux attendre la fin de toutes les itérations et diviser plutôt que de diviser par 1000 à chaque itération. C'est la fameuse vectorisation.
Une chose qui peut-être faite très simplement c'est de compiler ces fonctions avec la fonction cmpfun du package compiler. Des fois juste en utilisant la version normale ou la version compilée d'une même fonction le gain de temps peut-être appréciable.
Le choix des objets est aussi important. Si tu ne travailles que sur des données de même type alors privilégie la matrice au data.frame par exemple. Si je reprends le premier exemple et que j'applique la fonction colMeans par exemple, sur le data.frame et son clone sous forme de matrice :
Nik a raison quand il dit que R ne travaille par défaut qu'avec un seul cœur de ton ordi. Si tu fais pas de calculs matriciels ou appel à des fonctions qui sont basées dessus, comme tout ce qui concerne les analyses multivariées, les modèles linéaires, etc. Alors je te conseille d'installer la version de R développée par Microsoft R Open. Elle est basée sur des librairies différentes pour les calculs matricielles. Ces librairies sont parallélisées et sans que tu t'en rendes compte tu fais du calcul matriciel en parallèle, ce qui permet dans ce cas précis de gagner du temps aussi.
Sinon pour ce qui concerne le calcul parallèle, je te dis juste de faire attention. Comme pour tout, mal pensé et/ou mal programmé il peut s'avérer encore plus long que le calcul en série. Si le calcul à chaque itération n'est pas trop long alors ça ne vaudra pas le coup. Pour une boucle de 1000 itérations et 4 coeurs, il est parfois plus rentable de paralléliser une boucle 250 itérations sur chaque cœur (4 * 250 = 1000), que de lancer la boucle de 1000 en parallèle avec une seule itération faite à chaque fois sur un coeur. Au final on aura bien fait 1000 itérations, en parallèle, mais de manières différentes avec des temps de calculs très différents. Le choix du type de cluster, "SOCK", "FORK", etc. dépendra aussi de ta plateforme et aura un impact sur le temps de calcul. Si tu es sous Linux privilégie plutôt le FORK au SOCK. Sous windows pas le choix ça sera du SOCK. Après il y a aussi le type de parallélisation qui va jouer. Si toutes tes itérations sont supposées prendre le même temps alors tu gardes le types de parallélisation par défaut, si tu penses au contraire qu'il peut y avoir de grandes disparité en temps dans le calcul alors pars plutôt pour de la parallélisation de type load balancing et les fonctions de parallélisation se terminant par LB (parSapplyLB, etc.).
Pour résumé le plus rapidement ce que tu peux faire :
- compiler tes fonctions si ce n'est pas fait par défaut
- vectoriser tes calculs, sortir de la boucle tout ce qui peut-être fait en dehors
- profiler ton code ou utiliser microbenchmark pour comparer le temps d'exécution deux fonctions qui font le même travail
- utiliser MRO si tu fais du matriciel
- paralleliser
HTH
cdlt
Dans la famille des apply, très souvent c'est le vapply le plus rapide. La fonction apply étant la plus lente de sa famille (pour travailler sur un data.frame, un array ou une matrice). Après les fonctions apply and co ne sont que des alias qui renvoient vers des boucles ... via des fonctions compilées. Très souvent la boucle est plus lente que ces fonctions parce que mal programmée. Un exemple, le calcul de la moyenne des colonnes d'un tableau de 1000 * 1000 :
- Code:
fun <- function(tab) {
res <- numeric(ncol(tab))
u <- 1
for (i in tab) {
res[u] <- mean(i)
u <- u+1
}
res
}
fun <- compiler:::cmpfun(fun)
tab <- as.data.frame(matrix(rnorm(1e6),1e3))
Unit: milliseconds
expr min lq mean median uq max neval
fun(tab) 10.59437 10.70858 11.03133 10.84903 11.03667 15.22613 100
sapply(tab, mean) 11.54315 11.68945 11.95098 11.81234 11.99111 15.68220 100
Après je partage (en partie) l'avis de Nik. La question des boucles est récurrente et dépend du contexte et de ce que l'on souhaite faire.
La chose certaine à éviter ce sont les boucles emboitées. Plusieurs boucles les unes dans les autres et c'est vite la catastrophe. Mais pour éviter ça on peut générer l'ensemble des combinaisons i, j, k, ... dans un data.frame via expand.grid et ne faire qu'une boucle sur les lignes de ce data.frame par exemple.
Ce qui semble important de faire aussi avec les boucles dans les dernières version de R qui utilisent la compilation Just In Time par défaut (fonction enableJIT du package compiler), c'est des les "encapsuler" dans une fonction, pour que cette dernière soit compilée et que le calcul aille plus vite (voir précédent exemple). Je ne suis pas réellement arrivé à savoir si les boucles étaient elles aussi compiler (tous mes tests en ce sens ne se sont pas révélés concluants).
De manière générale, Nik à raison il te faut identifier via du profiling les sources de lenteur de ton code, voir si tu ne peux pas les programmer autrement en les vectorisant par exemple. L'autre chose est aussi de sortir de la boucle toutes les opérations qui peuvent ne se faire qu'une seule fois. Par exemple si à chaque itération tu divises un résultat par 1000, alors il vaut mieux attendre la fin de toutes les itérations et diviser plutôt que de diviser par 1000 à chaque itération. C'est la fameuse vectorisation.
Une chose qui peut-être faite très simplement c'est de compiler ces fonctions avec la fonction cmpfun du package compiler. Des fois juste en utilisant la version normale ou la version compilée d'une même fonction le gain de temps peut-être appréciable.
- Code:
Unit: milliseconds
expr min lq mean median uq max neval
fun(tab) 9.232556 10.95115 11.19212 11.14314 11.37778 21.72108 100
fun2(tab) 10.947756 13.07807 13.43691 13.30158 13.57454 17.09574 100
Le choix des objets est aussi important. Si tu ne travailles que sur des données de même type alors privilégie la matrice au data.frame par exemple. Si je reprends le premier exemple et que j'applique la fonction colMeans par exemple, sur le data.frame et son clone sous forme de matrice :
- Code:
mat <- as.matrix(tab)
Unit: milliseconds
expr min lq mean median uq max neval
colMeans(tab) 15.158924 15.403197 21.473626 15.783954 20.193335 171.183964 100
colMeans(mat) 1.835638 1.862822 1.916679 1.867541 1.872638 2.907118 100
Nik a raison quand il dit que R ne travaille par défaut qu'avec un seul cœur de ton ordi. Si tu fais pas de calculs matriciels ou appel à des fonctions qui sont basées dessus, comme tout ce qui concerne les analyses multivariées, les modèles linéaires, etc. Alors je te conseille d'installer la version de R développée par Microsoft R Open. Elle est basée sur des librairies différentes pour les calculs matricielles. Ces librairies sont parallélisées et sans que tu t'en rendes compte tu fais du calcul matriciel en parallèle, ce qui permet dans ce cas précis de gagner du temps aussi.
Sinon pour ce qui concerne le calcul parallèle, je te dis juste de faire attention. Comme pour tout, mal pensé et/ou mal programmé il peut s'avérer encore plus long que le calcul en série. Si le calcul à chaque itération n'est pas trop long alors ça ne vaudra pas le coup. Pour une boucle de 1000 itérations et 4 coeurs, il est parfois plus rentable de paralléliser une boucle 250 itérations sur chaque cœur (4 * 250 = 1000), que de lancer la boucle de 1000 en parallèle avec une seule itération faite à chaque fois sur un coeur. Au final on aura bien fait 1000 itérations, en parallèle, mais de manières différentes avec des temps de calculs très différents. Le choix du type de cluster, "SOCK", "FORK", etc. dépendra aussi de ta plateforme et aura un impact sur le temps de calcul. Si tu es sous Linux privilégie plutôt le FORK au SOCK. Sous windows pas le choix ça sera du SOCK. Après il y a aussi le type de parallélisation qui va jouer. Si toutes tes itérations sont supposées prendre le même temps alors tu gardes le types de parallélisation par défaut, si tu penses au contraire qu'il peut y avoir de grandes disparité en temps dans le calcul alors pars plutôt pour de la parallélisation de type load balancing et les fonctions de parallélisation se terminant par LB (parSapplyLB, etc.).
Pour résumé le plus rapidement ce que tu peux faire :
- compiler tes fonctions si ce n'est pas fait par défaut
- vectoriser tes calculs, sortir de la boucle tout ce qui peut-être fait en dehors
- profiler ton code ou utiliser microbenchmark pour comparer le temps d'exécution deux fonctions qui font le même travail
- utiliser MRO si tu fais du matriciel
- paralleliser
HTH
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
Merci à tous pour ces informations,
Eric Wajnberg
Ayana
D'accord, je vais utiliser cette fonction compile() et également optimiser mon code afin de réduire les itérations inutiles.
Pensez-vous que ça vaut le coup de se former au langage C, pour les gains qu'on peut avoir, au détriment du temps de formation ? Je réalise assez souvent des simulations et je me vois utiliser R toute ma vie.
Nik
Ce que tu expliques au niveau des coeurs est-il lié au fait d'utiliser Intel core I7 ou Intel core I5 ? Je suis sous le 5 et j'ai malheureusement 4Go de RAM sur mon PC professionnel.
J'entends bien ce que tu dis mais je n'arrive pas à le visualiser, est-ce que le fait de créer des objets vides à remplir au fur et à mesure ressemble au code suivant ?
Droopy
Merci pour toutes ces astuces, il est vrai que j'ai pour mauvaise habitude d'appliquer une même formule itérée sur chacun de mes objets (ce qui au final est stupide).
Le parallélisme est donc le fait de lancer le code sur plusieurs cores (qu'ils soient tous issus du même ordinateur ou non) ?
Concernant Microsoft R Open, je vais le tester chez moi, dans mon labo on n'a malheureusement pas d'autorisations sur l'installation de logiciels.
Ah et une dernière question d'ailleurs, si tu es dans un cas de figure où tu es obligé de lancer 3 boucles for() (du moins dans la théorie) pour un hypercube, le mieux à faire est donc de lancer 2 boucles for avec 1 vapply() ? (si j'ai bien compris)
Bon je me rends compte que mon code est assez loin d'être optimisé, tout ça va me faire gagner des journées et des journées de simulations.
Merci beaucoup à tous pour tous vos conseils, je m'en vais de ce pas essayer ces méthodes.
Eric Wajnberg
Ayana
D'accord, je vais utiliser cette fonction compile() et également optimiser mon code afin de réduire les itérations inutiles.
Pensez-vous que ça vaut le coup de se former au langage C, pour les gains qu'on peut avoir, au détriment du temps de formation ? Je réalise assez souvent des simulations et je me vois utiliser R toute ma vie.
Nik
Ce que tu expliques au niveau des coeurs est-il lié au fait d'utiliser Intel core I7 ou Intel core I5 ? Je suis sous le 5 et j'ai malheureusement 4Go de RAM sur mon PC professionnel.
J'entends bien ce que tu dis mais je n'arrive pas à le visualiser, est-ce que le fait de créer des objets vides à remplir au fur et à mesure ressemble au code suivant ?
- Code:
a=vector()
for(i in 1:10){
a[i]=i+1
}
Droopy
Merci pour toutes ces astuces, il est vrai que j'ai pour mauvaise habitude d'appliquer une même formule itérée sur chacun de mes objets (ce qui au final est stupide).
Le parallélisme est donc le fait de lancer le code sur plusieurs cores (qu'ils soient tous issus du même ordinateur ou non) ?
Concernant Microsoft R Open, je vais le tester chez moi, dans mon labo on n'a malheureusement pas d'autorisations sur l'installation de logiciels.
Ah et une dernière question d'ailleurs, si tu es dans un cas de figure où tu es obligé de lancer 3 boucles for() (du moins dans la théorie) pour un hypercube, le mieux à faire est donc de lancer 2 boucles for avec 1 vapply() ? (si j'ai bien compris)
Bon je me rends compte que mon code est assez loin d'être optimisé, tout ça va me faire gagner des journées et des journées de simulations.
Merci beaucoup à tous pour tous vos conseils, je m'en vais de ce pas essayer ces méthodes.
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Bonjour,
la plupart des processeurs actuels, i3, i5 et i7 sont multicœurs, mais R par défaut n'utilise qu'un seul cœur pour faire les calculs. Ce qui veut dire que si tu as un ordi avec 8 cœurs alors tu n'utilises qu'un huitième de sa puissance pour faire les calculs. Ce qui est dommage non ?
L'exemple que tu donnes est effectivement a proscrire puisque à chaque itération tu l'écrases.
Après l'exemple n'est valable que pour la forme de la boucle, parce qu'ici ce que tu cherches à faire c'est d'ajouter 1 à des valeurs connues (1 à 10) donc c'est typiquement le genre de calculs qui peut être vectoriser et qui doit être fait en dehors de la boucle. Du genre :
Oui le parallélisme est le fait de se servir de plusieurs coeurs en même temps au lieu de ne s'en servir que d'un seul (par défaut). Après on entre encore dans un autre monde, parce qu'il y a pas mal de manières différentes et de packages pour faire du parallélisme. Créer la structure qui permet de faire du parallélisme prend du temps, ainsi que les échanges entre les coeurs, donc ça ne vaut le coup que si les temps de calculs sont longs, sinon aucun intérêt. Dans mon précédent exemple, typiquement ça n'aurait pas d'intérêt de paralléliser.
A priori, à tester, de trois boucles tu peux en revenir à une seule :
A tester sur des grosses boucles, j'avoue ne pas l'avoir fait.
cdlt
la plupart des processeurs actuels, i3, i5 et i7 sont multicœurs, mais R par défaut n'utilise qu'un seul cœur pour faire les calculs. Ce qui veut dire que si tu as un ordi avec 8 cœurs alors tu n'utilises qu'un huitième de sa puissance pour faire les calculs. Ce qui est dommage non ?
L'exemple que tu donnes est effectivement a proscrire puisque à chaque itération tu l'écrases.
- Code:
# mauvaise pratique n°1
a <- vector()
for (i in in 1:10)
a[i] <- i+1
# mauvaise pratique n°2 :
a <- NULL
for (i in 1:10)
a <- c(a, i+1)
# bonne pratique :
a <- integer(10)
for (i in seq_along(a))
a[i] <- i + 1
Après l'exemple n'est valable que pour la forme de la boucle, parce qu'ici ce que tu cherches à faire c'est d'ajouter 1 à des valeurs connues (1 à 10) donc c'est typiquement le genre de calculs qui peut être vectoriser et qui doit être fait en dehors de la boucle. Du genre :
- Code:
a <- 1:10
a <- a+1
Oui le parallélisme est le fait de se servir de plusieurs coeurs en même temps au lieu de ne s'en servir que d'un seul (par défaut). Après on entre encore dans un autre monde, parce qu'il y a pas mal de manières différentes et de packages pour faire du parallélisme. Créer la structure qui permet de faire du parallélisme prend du temps, ainsi que les échanges entre les coeurs, donc ça ne vaut le coup que si les temps de calculs sont longs, sinon aucun intérêt. Dans mon précédent exemple, typiquement ça n'aurait pas d'intérêt de paralléliser.
- Code:
library(parallel)
cl <- makeCluster(getOption("cl.cores", 4))
microbenchmark(mns <- parSapply(cl, tab, mean), mns <- sapply(tab, mean))
Unit: milliseconds
expr min lq mean median uq max neval
mns <- parSapply(cl, tab, mean) 118.600636 136.918972 152.442330 140.903148 178.542046 211.514523 100
mns <- sapply(tab, mean) 5.634669 6.077733 6.418282 6.217619 6.489648 8.172988 100
A priori, à tester, de trois boucles tu peux en revenir à une seule :
- Code:
loops <- expand.grid(i = 1:3, j = 1:2, k = 1:4)
loops <- loops[do.call(order, loops),]
loops <- as.matrix(loops)
for (v in 1:nrow(loops)) ...
A tester sur des grosses boucles, j'avoue ne pas l'avoir fait.
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
Je ne vois pas trop bien comment faire un job de statisticien sans connaitre un langage de programmation "évolué", comme le C, par exemple. Ca me parait incontournable. Pour ce qui est de faire de la simulation (mon activité principale), l'utilisation de ce genre de langages me parait encore plus indispensable. Un langage interprété comme R va vite devenir limité/limitant, je le crains.zezima a écrit:Eric Wajnberg
Ayana
D'accord, je vais utiliser cette fonction compile() et également optimiser mon code afin de réduire les itérations inutiles.
Pensez-vous que ça vaut le coup de se former au langage C, pour les gains qu'on peut avoir, au détriment du temps de formation ? Je réalise assez souvent des simulations et je me vois utiliser R toute ma vie.
Mais bon, ça n'engage que moi..
Eric.
Eric Wajnberg- Nombre de messages : 1238
Date d'inscription : 14/09/2012
Re: Les boucles sont déconseillées dans R ?
Pour ce que ça vaut, je ne connais pas d'autres langages que R ... mais il est vrai que je ne fais que peu de simulations qui demandent beaucoup de temps de calculs et que j'ai aussi accès à une ressource informatique conséquente.Eric Wajnberg a écrit:Je ne vois pas trop bien comment faire un job de statisticien sans connaitre un langage de programmation "évolué", comme le C, par exemple.
De plus plus ça va et plus R est efficace et après c'est une question de temps disponible pour se former à un autre langage.
On est d'accord :-)Eric Wajnberg a écrit:Mais bon, ça n'engage que moi..
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
Je suis d'accord avec Eric pour dire que la maîtrise d'un autre langage est toujours un plus, mais pour une grande majorité d'études de simulations, R suffit. Sur un projet de plusieurs mois, perdre un ou deux jours en temps de calcul n'est pas si désastreux. Je fais énormément de simulations avec R, utilisant des méthodes "lentes" de type imputation multiple par équations chainées. Je ne peux pas faire tourner cela sur mon ordinateur car en temps total ça durerait plus d'un mois, mais en parallèle sur le HPC de mon université, c'est réglé en 24h (ce qui te laisse un peu de répit pour finir d'autres trucs en cours). Par contre, il faut bien tester ton code avant car la moindre petite erreur et tu repars pour une longue attente.
Si ça peut te rassurer, regarde les papiers publiés par des grands biostats contemporains (D Rubin, I White, J Higgins, D Altman...) et ils utilisent principalement R et Stata. La RSS propose des formations à la simulation avec R et Stata, donc ne t'en fais pas. Essaie juste d'optimiser ton code au mieux.
Et au pire, profite des temps de calcul pour prendre un café!
Ayana
Si ça peut te rassurer, regarde les papiers publiés par des grands biostats contemporains (D Rubin, I White, J Higgins, D Altman...) et ils utilisent principalement R et Stata. La RSS propose des formations à la simulation avec R et Stata, donc ne t'en fais pas. Essaie juste d'optimiser ton code au mieux.
Et au pire, profite des temps de calcul pour prendre un café!
Ayana
Ayana- Nombre de messages : 550
Localisation : Londres
Date d'inscription : 18/08/2009
Re: Les boucles sont déconseillées dans R ?
Deux points en supplément de cette discussion.
1) Je fais de très lourds modèles de simulation (Monte Carlo), dans des conditions fortement stochastiques (écologie et comportement d'insectes). Un réplicat, sur une bonne machine, et codé en C, prend au mieux une vingtaine d'heures. Vue la stochasticité, je dois faire plusieurs centaines de réplicats pour récupérer une résultat moyen, et ce dans chacune des conditions comparées. Sur une machine linéaire, il me faudrait rapidement des années. Je fais donc tourner mes codes sur de très grosses grilles (clusters). Je n'ose imaginer comment je m'en sortirais si je devais faire tourner ceci codé en R, même en parallélisant, etc. Tout bonnement impossible.
2) R ok (et je l'utilise énormément), mais ça veut principalement dire utiliser des outils statistiques déjà existants. Parfois, il faut créer ses propres outils statistiques (dans mon cas lorsque j'ai des vraisemblances pas très propres à maximiser, ou bien des algorithmes génétiques avec des tournois, ou bien des calculs qui nécessitent l'usage de librairy de très grande précision, etc.). Dans ce cas, obligé de sortir de R (même si l'offre est riche), et il faut coder tout ceci de son côté.
Eric.
1) Je fais de très lourds modèles de simulation (Monte Carlo), dans des conditions fortement stochastiques (écologie et comportement d'insectes). Un réplicat, sur une bonne machine, et codé en C, prend au mieux une vingtaine d'heures. Vue la stochasticité, je dois faire plusieurs centaines de réplicats pour récupérer une résultat moyen, et ce dans chacune des conditions comparées. Sur une machine linéaire, il me faudrait rapidement des années. Je fais donc tourner mes codes sur de très grosses grilles (clusters). Je n'ose imaginer comment je m'en sortirais si je devais faire tourner ceci codé en R, même en parallélisant, etc. Tout bonnement impossible.
2) R ok (et je l'utilise énormément), mais ça veut principalement dire utiliser des outils statistiques déjà existants. Parfois, il faut créer ses propres outils statistiques (dans mon cas lorsque j'ai des vraisemblances pas très propres à maximiser, ou bien des algorithmes génétiques avec des tournois, ou bien des calculs qui nécessitent l'usage de librairy de très grande précision, etc.). Dans ce cas, obligé de sortir de R (même si l'offre est riche), et il faut coder tout ceci de son côté.
Eric.
Dernière édition par Eric Wajnberg le Mer 4 Oct 2017 - 13:06, édité 4 fois
Eric Wajnberg- Nombre de messages : 1238
Date d'inscription : 14/09/2012
Re: Les boucles sont déconseillées dans R ?
Bonjour,
ceci va dans le sens de mon précédent post, tout dépend de l'usage et des stats que l'on fait. Dans un cas comme le tien investir dans un autre langage fait sens, mais dans d'autres non. Le dernier point n'empêche pas de sortir de R, puisque nombres librairies sont développées pour étoffer l'offre. Les auteurs ayant développées de nouvelles méthodes en restant dans le langage. Comme souvent tout est une question de point de vue et d'utilisation.
cdlt
ceci va dans le sens de mon précédent post, tout dépend de l'usage et des stats que l'on fait. Dans un cas comme le tien investir dans un autre langage fait sens, mais dans d'autres non. Le dernier point n'empêche pas de sortir de R, puisque nombres librairies sont développées pour étoffer l'offre. Les auteurs ayant développées de nouvelles méthodes en restant dans le langage. Comme souvent tout est une question de point de vue et d'utilisation.
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
Droopy
Merci beaucoup droopy pour ces précisions.
Si je comprends bien, il est conseillé de déterminer la taille des objets qu'on va remplir en amont ?
Par exemple il est mieux de préciser qu'une liste sera de taille 1000 si on veut la remplir de 1000 vecteurs (et qu'on a l'information en amont) ?
A priori, sur des codes longs (qui ne se comptent pas en secondes ou en minutes), le parallélisme l'emportera toujours sur le mono-coeur ?
Penses-tu qu'il est possible de bannir les boucles for() pour tous les cas de figures possibles si on maîtrise totalement le code R ?
Je suis en train de me mettre aux lapply, vapply, sapply, mais il me semble que certains cas de figures ne peuvent pas être réalisés sans une boucles for(), exemple :
Je voudrais créer 1000 vecteurs de 6 valeurs compris dans une liste.
Chaque liste est une courbe pour laquelle on a les valeurs de 6 points dépendant d'une formule :
Bon je divague mais je pense que c'est peut-être toujours dans la même optique.
Eric
Si C fait gagner un temps fou alors je m'y mettrais mais je pense qu'il y a un grand nombre d'étapes qui doivent précéder son utilisation, je ne suis pas un adepte de la programmation pure et dure pour le moment.
Et ça fait parti de mes objectifs car je commence à faire du Monte-Carlo et le nombre d'itérations peut vite devenir long.
Merci beaucoup droopy pour ces précisions.
Si je comprends bien, il est conseillé de déterminer la taille des objets qu'on va remplir en amont ?
Par exemple il est mieux de préciser qu'une liste sera de taille 1000 si on veut la remplir de 1000 vecteurs (et qu'on a l'information en amont) ?
A priori, sur des codes longs (qui ne se comptent pas en secondes ou en minutes), le parallélisme l'emportera toujours sur le mono-coeur ?
Penses-tu qu'il est possible de bannir les boucles for() pour tous les cas de figures possibles si on maîtrise totalement le code R ?
Je suis en train de me mettre aux lapply, vapply, sapply, mais il me semble que certains cas de figures ne peuvent pas être réalisés sans une boucles for(), exemple :
Je voudrais créer 1000 vecteurs de 6 valeurs compris dans une liste.
Chaque liste est une courbe pour laquelle on a les valeurs de 6 points dépendant d'une formule :
- Code:
result=list(rep("",1000))
d=1:6
a=rnorm(1000,0,1)
b=rnorm(1000,1,2)
c=rnorm(1000,20,1)
#Formule : result=c+(a*d)/(b+d)
result=c+(a*d)/(b+d) #Ce code ne marche pas
for(i in 1:1000){result[[i]]=c[[i]]+(a[[i]]*d)/(b[[i]]+d)} #Ce code marche mais nécessite une boucle for()
#On obtient finalement la liste de vecteurs de taille 6
Bon je divague mais je pense que c'est peut-être toujours dans la même optique.
Eric
Si C fait gagner un temps fou alors je m'y mettrais mais je pense qu'il y a un grand nombre d'étapes qui doivent précéder son utilisation, je ne suis pas un adepte de la programmation pure et dure pour le moment.
Et ça fait parti de mes objectifs car je commence à faire du Monte-Carlo et le nombre d'itérations peut vite devenir long.
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Il est clair que C te fera gagner énormément de temps au niveau du calcul. Ce qu'il te faut voir c'est le temps que ça va te prendre de développer le code C + le temps de calcul, par rapport à la même chose en R.
Par rapport à ton exemple je vois deux problème. D'une part la liste qui n'est pas nécessaire. Le résultat de ton calcul est toujours un vecteur de 6 valeurs numériques donc une matrice de 1000 lignes et de 6 colonnes permettra de stocker l'info. Le deuxième problème que je vois, c'est que ce qui change entre chaque opération ce sont les valeurs de d et non pas les autres valeurs, tu auras toujours la même valeur pour a, b et d. Donc tu peux juste boucler sur les valeurs de d plutôt que sur chacune des valeurs de a, b, etc. Donc au final tu passes d'une boucle sur 1000 valeurs à une boucle sur 6, c'est ce dont Eric parlait, il faut vectoriser tes calculs :
Voila ce que ça donne en temps de calculs :
liste : ta boucle et Loop6 la boucle que sur les 6 valeurs de d.
cdlt
Par rapport à ton exemple je vois deux problème. D'une part la liste qui n'est pas nécessaire. Le résultat de ton calcul est toujours un vecteur de 6 valeurs numériques donc une matrice de 1000 lignes et de 6 colonnes permettra de stocker l'info. Le deuxième problème que je vois, c'est que ce qui change entre chaque opération ce sont les valeurs de d et non pas les autres valeurs, tu auras toujours la même valeur pour a, b et d. Donc tu peux juste boucler sur les valeurs de d plutôt que sur chacune des valeurs de a, b, etc. Donc au final tu passes d'une boucle sur 1000 valeurs à une boucle sur 6, c'est ce dont Eric parlait, il faut vectoriser tes calculs :
- Code:
# ton code
result=list(rep("",1000))
d=1:6
a=rnorm(1000,0,1)
b=rnorm(1000,1,2)
c=rnorm(1000,20,1)
#Formule : result=c+(a*d)/(b+d)
# result=c+(a*d)/(b+d) #Ce code ne marche pas
for(i in 1:1000){
result[[i]]=c[[i]]+(a[[i]]*d)/(b[[i]]+d)
}
# je stocke les résultats en matrice pour les comparer avec la suite
res <- do.call(rbind, result)
# une boucle possible :
mat <- matrix(numeric(), 1e3, 6)
for (i in 1:6){
mat[,i] <- c + (d[i]*a)/(b+d[i])
}
- Code:
mat2 <- matrix(numeric(), 1e3, 6)
for (i in 1:6){
mat2[,i] <- (d[i]*a)/(b+d[i])
}
mat2 <- mat2 + c
- Code:
mat3 <- vapply(d, function(x) c + (x*a)/(b+x), numeric(1000))
mat4 <- sapply(d, function(x) c + (x*a)/(b+x))
Voila ce que ça donne en temps de calculs :
- Code:
expr min lq mean median uq max neval
liste 1810.726 1872.2205 1948.3374 1892.3100 1924.7085 4643.714 1000
Vapply 113.487 117.1720 150.9318 118.6790 121.2310 4493.728 1000
Sapply 166.952 172.5405 267.7713 176.8655 185.4840 55914.830 1000
Loop6 137.292 142.1725 185.1154 144.1095 147.0465 3755.548 1000
liste : ta boucle et Loop6 la boucle que sur les 6 valeurs de d.
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
On aurait pu même ne pas utiliser de boucle :
cdlt
- Code:
d2 <- matrix(as.numeric(d), length(d), length(a))
d2 <- t(d2)
mat <- c + (d2*a)/(b+d2)
cdlt
droopy- Nombre de messages : 1156
Date d'inscription : 04/09/2009
Re: Les boucles sont déconseillées dans R ?
Merci énormément pour ce cours interactif droopy.
Excuse-moi du retard de réponse, je suis overbooké en ce moment (surement à cause de mes simulations trop lentes).
C'est très intéressant et je me rends compte que mon code était... horrible avant que je ne crée ce topic.
Mention spéciale à vapply que je trouve particulièrement performant.
Je pense que ma prochaine étape sera de me mettre au langage C et à Rstan (petit à petit bien sur).
Excuse-moi du retard de réponse, je suis overbooké en ce moment (surement à cause de mes simulations trop lentes).
C'est très intéressant et je me rends compte que mon code était... horrible avant que je ne crée ce topic.
Mention spéciale à vapply que je trouve particulièrement performant.
Je pense que ma prochaine étape sera de me mettre au langage C et à Rstan (petit à petit bien sur).
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Eric Wajnberg a écrit:Enfin, la solution que je préfère, est de coder la simulation en C, et d'intégrer le code C compilé dans R, avec la fonction .C(). Ca demande un peu de pratique, mais c'est clairement la solution la plus rapide pour faire de la simulation, et ça offre d'un coup tout les outils statistiques et graphiques de R (par exemple pour analyser les résultats), ce qui est vraiment appréciable.
Bonjour Eric, lorsque tu dis que C est vraiment le must pour faire tourner des simulations, le concept est de remplacer toutes les boucles et toutes les fonctions qui vont être utilisées dans R, de les compiler et enfin de lancer la simulation ?
Je vais me lancer dans quelques semaine dans le langage C je pense mais je préfère être sur de ce qu'il va falloir prendre en compte avant.
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Tout ce qui peut être fait en C doit y être fait. C'est à dire, les boucles, les calculs en tout genre, etc. Y compris la lecture des données et/ou des paramètres (if any). Le coeur du code C doit être autonome, jusqu'à la sortie des résultats, qui peuvent être récupérer par R pour faire des graphs, des stats, etc.
Encore une fois, c'est comme ceci que je procède. On peut déléguer R au besoin des parties des calculs (par exemple tirage de valeurs pseudo-aléatoires, calcul matriciel, etc.) mais je préfère éviter pour réduire au maximum les temps de calcul.
HTH, Eric.
Encore une fois, c'est comme ceci que je procède. On peut déléguer R au besoin des parties des calculs (par exemple tirage de valeurs pseudo-aléatoires, calcul matriciel, etc.) mais je préfère éviter pour réduire au maximum les temps de calcul.
HTH, Eric.
Eric Wajnberg- Nombre de messages : 1238
Date d'inscription : 14/09/2012
Re: Les boucles sont déconseillées dans R ?
Ah d'accord donc même les simulations doivent potentiellement être faites sous C.
Merci pour ces infos
Merci pour ces infos
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Re: Les boucles sont déconseillées dans R ?
Encore une fois, pas forcément. Mais c'est ce que je fais moi, et ca gagne beaucoup de temps, je pense.
Eric
Eric
Eric Wajnberg- Nombre de messages : 1238
Date d'inscription : 14/09/2012
Re: Les boucles sont déconseillées dans R ?
Bonjour,
Je reviens vers vous au sujet de la parallélisation sous R.
Vous m'aviez conseillé d'installer Microsoft R Open qui réalise le parallélisme sans qu'on s'en rende compte.
Cependant je n'ai pas la possibilité de l'installer dans la structure où je travaille.
Je me penche donc vers les librairies mais il y en a plusieurs apparemment.
library(parallel) #semble pas mal pour les boucles lapply
library(doRNG) #idem et fait appel à la librairie foreach donc potentiellement plus évolué
library(doParallel) #idem
library(foreach) #conseillé pour les matrices et listes
Je ne sais pas quelle librairie serait la plus optimale, j'utilise surtout les fonctions lapply(), sapply(), vapply() et apply() (et parfois les boucles for() pour de petits calculs). Etant donné que je lance neuf milliards de calculs de Residual Sum of Square, je pense que le choix peut avoir un gros impact (pour le moment je prends 3 jours pour tout lancer).
Savez-vous quelle librairie est la plus adaptée ?
(je précise que je suis sous Windows et sous R.3.2.1)
Ah et j'ai également entendu dire que Microsoft R Open est plus rapide que R avec un code optimisé pour la parallélisation (lui-même plus rapide que R-studio), est-ce que vous avez entendu parler de cette comparaison ? Cela peut m'être utile à domicile.
Merci
Je reviens vers vous au sujet de la parallélisation sous R.
Vous m'aviez conseillé d'installer Microsoft R Open qui réalise le parallélisme sans qu'on s'en rende compte.
Cependant je n'ai pas la possibilité de l'installer dans la structure où je travaille.
Je me penche donc vers les librairies mais il y en a plusieurs apparemment.
library(parallel) #semble pas mal pour les boucles lapply
library(doRNG) #idem et fait appel à la librairie foreach donc potentiellement plus évolué
library(doParallel) #idem
library(foreach) #conseillé pour les matrices et listes
Je ne sais pas quelle librairie serait la plus optimale, j'utilise surtout les fonctions lapply(), sapply(), vapply() et apply() (et parfois les boucles for() pour de petits calculs). Etant donné que je lance neuf milliards de calculs de Residual Sum of Square, je pense que le choix peut avoir un gros impact (pour le moment je prends 3 jours pour tout lancer).
Savez-vous quelle librairie est la plus adaptée ?
(je précise que je suis sous Windows et sous R.3.2.1)
Ah et j'ai également entendu dire que Microsoft R Open est plus rapide que R avec un code optimisé pour la parallélisation (lui-même plus rapide que R-studio), est-ce que vous avez entendu parler de cette comparaison ? Cela peut m'être utile à domicile.
Merci
zezima- Nombre de messages : 939
Date d'inscription : 26/02/2013
Sujets similaires
» Problème dans le package ensembleBMA dans R
» mes données sont-il significativement différentent
» Probabilité tirage type loto
» Nos statisticiens sont en vacance ? Test KW
» Les différences sont elles significatives?
» mes données sont-il significativement différentent
» Probabilité tirage type loto
» Nos statisticiens sont en vacance ? Test KW
» Les différences sont elles significatives?
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum