web-dev-qa-db-fra.com

Dans Scipy, comment et pourquoi curve_fit calcule la covariance des estimations des paramètres

J'utilise scipy.optimize.leastsq Pour ajuster certaines données. Je voudrais obtenir des intervalles de confiance sur ces estimations, donc je regarde la sortie cov_x Mais la documentation n'est pas très claire sur ce que c'est et comment obtenir la matrice de covariance pour mes paramètres à partir de cela.

Tout d'abord, il est dit que c'est un jacobien, mais dans le notes , il est également dit que "cov_x Est une approximation jacobienne de la Hesse", de sorte que ce n'est pas réellement un jacobien mais un Hessian utilisant une approximation du Jacobian. Laquelle de ces affirmations est correcte?

Deuxièmement, cette phrase me déroute:

Cette matrice doit être multipliée par la variance résiduelle pour obtenir la covariance des estimations des paramètres - voir curve_fit.

Je vais en effet regarder le code source de curve_fit Où ils le font:

s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0))
pcov = pcov * s_sq

ce qui correspond à la multiplication de cov_x par s_sq mais je ne trouve cette équation dans aucune référence. Quelqu'un peut-il expliquer pourquoi cette équation est correcte? Mon intuition me dit que ce devrait être l'inverse puisque cov_x Est censé être un dérivé (jacobien ou hessois) donc je pensais: cov_x * covariance(parameters) = sum of errors(residuals)sigma(parameters) est la chose que je veux.

Comment puis-je connecter la chose que courbe_fit fait avec ce que je vois par exemple. wikipedia: http://en.wikipedia.org/wiki/Propagation_of_uncertainty#Non-linear_combinations

31
HansHarhoff

OK, je pense avoir trouvé la réponse. D'abord la solution: cov_x * s_sq est simplement la covariance des paramètres qui est ce que vous voulez. Prendre sqrt des éléments diagonaux vous donnera l'écart-type (mais faites attention aux covariances!).

Variance résiduelle = chi carré réduit = s_sq = somme [(f (x) -y) ^ 2]/(N-n), où N est le nombre de points de données et n est le nombre de paramètres d'ajustement. carré chi réduit .

La raison de ma confusion est que cov_x tel que donné par lesssq n'est pas réellement ce qu'on appelle cov (x) dans d'autres endroits, mais plutôt le cov réduit (x) ou le cov fractionnel (x). La raison pour laquelle il n'apparaît dans aucune des autres références est qu'il s'agit d'un simple redimensionnement qui est utile dans les calculs numériques, mais n'est pas pertinent pour un manuel.

À propos de la Hesse et de la Jacobie, la documentation est mal formulée. C'est le Hessian qui est calculé dans les deux cas comme cela est évident puisque le Jacobian est nul au minimum. Ce qu'ils veulent dire, c'est qu'ils utilisent une approximation du jacobien pour trouver le hessien.

Une autre note. Il semble que le résultat curve_fit ne tienne pas réellement compte de la taille absolue des erreurs, mais ne prenne en compte que la taille relative des sigmas fournis. Cela signifie que le pcov retourné ne change pas même si les barres d'erreur changent d'un facteur un million. Ce n'est bien sûr pas correct, mais cela semble être une pratique standard, c'est-à-dire. Matlab fait la même chose lors de l'utilisation de sa boîte à outils d'ajustement de courbe. La procédure correcte est décrite ici: https://en.wikipedia.org/wiki/Linear_least_squares_ (mathématiques) #Parameter_errors_and_correlation

Il semble assez simple de le faire une fois l'optimum trouvé, du moins pour les moindres carrés linéaires.

26
HansHarhoff

J'ai trouvé cette solution lors de ma recherche d'une question similaire, et je n'ai qu'une petite amélioration sur la réponse de HansHarhoff. La sortie complète de lesssq fournit une valeur de retour infodict, qui contient infodict ['fvec'] = f(x) -y. Ainsi, pour calculer le chi carré réduit = (dans la notation ci-dessus) )

s_sq = (infodict['fvec']**2).sum()/ (N-n)

BTW. Merci HansHarhoff d'avoir fait la plupart des efforts lourds pour résoudre ce problème.

7
Jim Parker