Obtenir les bonnes valeurs de départ pour un modèle nls dans R

12

J'essaie d'adapter un modèle de loi de puissance simple à un ensemble de données qui se présente comme suit:

mydf:

rev     weeks
17906.4 1
5303.72 2
2700.58 3
1696.77 4
947.53  5
362.03  6

L'objectif étant de faire passer la ligne électrique et de l'utiliser pour prédire les revvlaues pour les semaines à venir. Un tas de recherches m'a conduit à la nlsfonction, que j'ai implémentée comme suit.

newMod <- nls(rev ~ a*weeks^b, data=modeldf, start = list(a=1,b=1))
predict(newMod, newdata = data.frame(weeks=c(1,2,3,4,5,6,7,8,9,10)))

Bien que cela fonctionne pour un lmmodèle, j'obtiens une singular gradienterreur, qui, je crois, a à voir avec mes valeurs de départ aet b. J'ai essayé différentes valeurs, allant même jusqu'à tracer cela dans Excel, passer un seul, obtenir une équation, puis utiliser les valeurs de l'équation, mais j'obtiens toujours l'erreur. J'ai regardé un tas de réponses comme celle-ci et essayé la deuxième réponse (je ne pouvais pas comprendre la première), mais sans résultat.

Je pourrais vraiment utiliser une aide ici sur la façon de trouver les bonnes valeurs de départ. Ou bien, quelle autre fonction je peux utiliser à la place de nls.

Si vous souhaitez recréer mydffacilement:

mydf <- data.frame(rev=c(17906.4, 5303.72, 2700.58 ,1696.77 ,947.53 ,362.03), weeks=c(1,2,3,4,5,6)) 
NeonBlueHair
la source
1
Bien qu'énoncé en termes de R (cela doit vraiment être indiqué dans un certain langage), la façon de trouver des valeurs de départ appropriées pour un ajustement de modèle non linéaire est suffisamment statistique pour être sur le sujet ici, OMI. Ce n'est pas vraiment un Q de programmation, par exemple.
gung - Rétablir Monica

Réponses:

13

Il s'agit d'un problème courant avec les modèles de moindres carrés non linéaires; si vos valeurs de départ sont très éloignées de l'optimum, l'algorithme peut ne pas converger, même s'il se comporte bien près de l'optimum.

log(a)b

ab

 newMod <- nls(rev ~ a*weeks^b, data=mydf, start = list(a=exp(9.947),b=-2.011))
 predict(newMod, newdata = data.frame(weeks=c(1,2,3,4,5,6,7,8,9,10)))
 [1] 17919.2138  5280.7001  2584.0109  1556.1951  1050.1230   761.4947   580.3091   458.6027
 [9]   372.6231   309.4658
Glen_b -Reinstate Monica
la source
C'est extrêmement utile, merci beaucoup! J'ai une question sur la façon dont vous avez obtenu votre valeur "a" ici. J'ai essayé d'exécuter lm (log10 (rev) ~ log10 (semaines)) puis d'utiliser la fonction "résumé", et bien que j'obtienne la même valeur "b", ma valeur "a" ressort à 4.3201. Qu'avez-vous fait différemment pour arriver à a = 9,947?
NeonBlueHair
exploge
Ah, tu as tout à fait raison. Erreur amateur de ma part. Pensée continue de la notation mathématique en s'attendant à ce que «log» signifie la base de log 10 et «ln» pour le log naturel. Merci pour la clarification.
NeonBlueHair
1
Pour de nombreux mathématiciens (et de nombreux statisticiens), un «log» sans fioritures est le logarithme naturel, tout comme un argument sans fioritures à une fonction de péché est en radians. [Les conventions conflictuelles peuvent conduire à la confusion, malheureusement, mais lorsque j'ai commencé à utiliser R, par exemple, je n'ai pas réfléchi à deux fois à l'utilisation de la fonction de journalisation car R et moi partageons la même convention.]
Glen_b -Reinstate Monica
4

Essayer

 newMod <- nls(rev ~ a*weeks^b, data=mydf, startlist(a=17919.2127344,b=-1.76270557120))

On m'a demandé d'élargir un peu cette réponse. Ce problème est si simple que je suis un peu surpris que nls y échoue. Le vrai problème est cependant avec toute l'approche R et la philosophie de l'ajustement de modèle non linéaire. Dans le monde réel, l'échelle serait x pour se situer entre -1 et 1 et y et y pour se situer entre 0 et 1 (y = ax ^ b). Ce serait probablement suffisant pour faire converger nls. Bien sûr, comme Glen le fait remarquer, vous pouvez adapter le modèle log-linéaire correspondant. Cela repose sur le fait qu'il existe une simple transformation qui linéarise le modèle. Ce n'est souvent pas le cas. Le problème avec les routines R comme nls est qu'elles n'offrent pas de support pour reparameter le modèle. Dans ce cas, la reparamétrie est simple, il suffit de redimensionner / recentrer x et y. Cependant, après avoir ajusté le modèle, l'utilisateur aura des paramètres a et b différents de ceux d'origine. S'il est simple de calculer les originaux à partir de ceux-ci, l'autre difficulté est qu'il n'est pas si simple en général d'obtenir les écarts-types estimés pour ces estimations de paramètres. Cela se fait par la méthode delta qui implique la Hesse de la log-vraisemblance et certaines dérivées. Un logiciel d'estimation de paramètres non linéaire devrait fournir ces calculs automatiquement, afin que la reparamétrisation du modèle soit facilement prise en charge. Une autre chose que les logiciels devraient prendre en charge est la notion de phases. Vous pouvez penser à adapter d'abord le modèle avec la version de Glen comme phase 1. Le "vrai" modèle est adapté à l'étape 2. l'autre difficulté est qu'il n'est pas si simple en général d'obtenir les écarts-types estimés pour ces estimations de paramètres. Cela se fait par la méthode delta qui implique la Hesse de la log-vraisemblance et certaines dérivées. Un logiciel d'estimation de paramètres non linéaire devrait fournir ces calculs automatiquement, afin que la reparamétrisation du modèle soit facilement prise en charge. Une autre chose que les logiciels devraient prendre en charge est la notion de phases. Vous pouvez penser à adapter d'abord le modèle avec la version de Glen comme phase 1. Le "vrai" modèle est adapté à l'étape 2. l'autre difficulté est qu'il n'est pas si simple en général d'obtenir les écarts-types estimés pour ces estimations de paramètres. Cela se fait par la méthode delta qui implique la Hesse de la log-vraisemblance et certaines dérivées. Un logiciel d'estimation de paramètres non linéaire devrait fournir ces calculs automatiquement, afin que la reparamétrisation du modèle soit facilement prise en charge. Une autre chose que les logiciels devraient prendre en charge est la notion de phases. Vous pouvez penser à adapter d'abord le modèle avec la version de Glen comme phase 1. Le "vrai" modèle est adapté à l'étape 2. Un logiciel d'estimation de paramètres non linéaire devrait fournir ces calculs automatiquement, afin que la reparamétrisation du modèle soit facilement prise en charge. Une autre chose que les logiciels devraient prendre en charge est la notion de phases. Vous pouvez penser à adapter d'abord le modèle avec la version de Glen comme phase 1. Le "vrai" modèle est adapté à l'étape 2. Un logiciel d'estimation de paramètres non linéaire devrait fournir ces calculs automatiquement, afin que la reparamétrisation du modèle soit facilement prise en charge. Une autre chose que les logiciels devraient prendre en charge est la notion de phases. Vous pouvez penser à adapter d'abord le modèle avec la version de Glen comme phase 1. Le "vrai" modèle est adapté à l'étape 2.

J'adapte votre modèle avec AD Model Builder qui prend en charge les phases de manière naturelle. Dans la première phase, seul a a été estimé. Cela met votre modèle dans le stade. Dans la deuxième phase, a et b sont estimés pour obtenir la solution. AD Model Builder calcule automatiquement les écarts-types pour toute fonction des paramètres du modèle via la méthode delta afin d'encourager une reparamétrie stable du modèle.

dave fournier
la source
2

L'algorithme de Levenberg-Marquardt peut aider:

modeldf <- data.frame(rev=c(17906.4, 5303.72, 2700.58 ,1696.77 ,947.53 ,362.03), weeks=c(1,2,3,4,5,6))

require(minpack.lm)
fit <- nlsLM(rev ~ a*weeks^b, data=modeldf, start = list(a=1,b=1))

require(broom)
fit_data <- augment(fit)

plot(.fitted~rev, data=fit_data)
Etienne Low-Décarie
la source
1

D'après mon expérience, un bon moyen de trouver des valeurs de départ pour les paramètres des modèles NLR est d'utiliser un algorithme évolutif. À partir d'une population initiale (100) d'estimations aléatoires (parents) dans un espace de recherche, choisissez les 20 meilleurs (progéniture) et utilisez-les pour définir une recherche dans une population suivante. Répétez jusqu'à convergence. Pas besoin de gradients ou de toile de jute, juste des évaluations SSE. Si vous n'êtes pas trop gourmand, cela fonctionne très souvent. Les problèmes que les gens ont souvent, c'est qu'ils utilisent une recherche locale (Newton-Raphson) pour effectuer le travail d'une recherche globale. Comme toujours, il s'agit d'utiliser le bon outil pour le travail à accomplir. Il est plus judicieux d'utiliser une recherche globale EA pour trouver les valeurs de départ de la recherche locale de Newton, puis laissez-la fonctionner au minimum. Mais, comme pour tout, le diable est dans les détails.

Adrian O'Connor
la source