Aujourd'hui, nous finissons l'étude de cas entamée il y a un mois avec la solution de l'excercice suivant basé sur les « données POMC »…
Vous définirez une fonction de coût correspondant à ce modèle comme la somme des résidus aux carrés ; les résidus étant calculés à partir des données et de la prédiction stabilisés. Vous utiliserez ensuite minimize
et la méthode BFGS. Il faudra réfléchir un peu pour trouver les valeurs initiales. En utilisant les paramètres estimés, vous simulerez entre 500 et 1000 jeux de données en utilisant le « modèle exacte », c'est-à-dire :
Quelques indices :
%pylab
from __future__ import print_function, division, unicode_literals, absolute_import
import sympy as sy
sy.init_printing()
import urllib
urllib.urlretrieve("http://xtof.disque.math.cnrs.fr/data/Data_POMC.npz","Data_POMC.npz")
POMC = load("Data_POMC.npz")
temps_POMC = POMC['arr_0']
pile_POMC = POMC['arr_1']
POMC.close()
%matplotlib inline
Le gain et la variance de lecture du capteur CCD que nous avons déterminés sont :
G_chapeau = 0.147397980373
S2_chapeau = 268.741290284
La version stabilisée de pile_POMC
est simplement obtenue avec :
pile_POMC_stab = 2*sqrt(pile_POMC/G_chapeau+S2_chapeau)
La matrice des $RSS_{i,j}$ est obtenues avec :
pile_POMC_RSS = sum((pile_POMC_stab - pile_POMC_stab.mean(2).reshape((60,80,1)))**2,2)
Et le graphe des pixels tels que $\log\left(1 - F_{\chi_{K-1}^2}(RSS_{i,j})\right)$ est proche de $-\infty$ est construit avec :
from scipy.stats import chi2
pile_POMC_logCFRSS = log(1-chi2.cdf(pile_POMC_RSS,167))
imshow(transpose(pile_POMC_logCFRSS == -Inf),origin='lower')
set_cmap('gray')
Les pixels pour lesquels $\log\left(1 - F_{\chi_{K-1}^2}(RSS_{i,j})\right)$ est numériquement égale à $-\infty$ sont obtenus par un appel à la fonction where :
bons_pxl = where(pile_POMC_logCFRSS == -Inf)
Là, une impression du résultat montre que le pixel isolé est le dernier trouvé et les coordonnées des pixels connexes sont donc obtenues avec :
bons_pxl = [x[:(len(x)-1)] for x in bons_pxl]; bons_pxl
Nous allons obtenir une valeur intiale du vecteur $f_k$ en moyennant une version normalisée du décours temporel obtenu en chacun des pixels de notre région d'intérêt. Nous estimons la ligne de base de chaque pixel en moyennant les observations obtenues au cours des cinq premiers temps. Ici il faut faire un peu attention car notre région connexe ne constitue pas un rectangle, nous ne pouvons donc pas extraire les pixels intéressants et conserver une structure de pile. En extrayant les signaux des pixels d'intérêts, nous allons donc réduire la dimension des données (consultez la documentation de Advanced indexing pour plus de détails) :
bons_signaux = pile_POMC[bons_pxl[0],bons_pxl[1],:]
ligne_de_base = bons_signaux[:,:5].mean(1)
f_0 = mean(bons_signaux/ligne_de_base.reshape(35,1),0)
b_0 = 100
phi_0 = [(len(f_0)*sum(f_0*y)-sum(f_0)*sum(y))/(len(f_0)*sum(f_0**2)-sum(f_0)**2) for y in bons_signaux.tolist()]
def var_stab(x,G=G_chapeau,S2=S2_chapeau): return 2*sqrt(x/G+S2)
par_0 = zeros((1+35+167,))
par_0[0] = b_0
par_0[1:36] = phi_0
par_0[36:] = f_0[1:]
def fait_rss(donnees):
npix,K = donnees.shape
f = ones((K,))
def rss(par):
par = exp(par)
b = par[0]
phi = par[1:(npix+1)]
f[1:] = par[(npix+1):]
pred = var_stab(outer(phi,f)+b)
return sum((donnees-pred)**2)
return rss
bons_signaux_stab = var_stab(bons_signaux)
rss0 = fait_rss(bons_signaux_stab)
rss0(log(par_0))
from scipy.optimize import minimize
ajuste0 = minimize(rss0,log(par_0),method='nelder-mead',options={'disp': True})
ajuste0 = minimize(rss0,ajuste0.x,method='nelder-mead',options={'disp': True})
ajuste0 = minimize(rss0,ajuste0.x,method='BFGS',options={'disp': True})
ajuste0 = minimize(rss0,ajuste0.x,method='nelder-mead',options={'disp': True})
b_1 = exp(ajuste0.x[0])
phi_1 = exp(ajuste0.x[1:36])
f_1 = ones((bons_signaux.shape[1],))
f_1[1:] = exp(ajuste0.x[36:])
plot(f_1)