Como una especie de prueba de principio estoy tratando de estimar los parámetros de una ecuación lineal (antes de pasar a las EDOs) utilizando el muestreo de Monte Carlo de cadenas de Markov. El post que estoy siguiendo se puede encontrar en este enlace https://sciencehouse.wordpress.com/2010/06/23/mcmc-and-fitting-models-to-data/
Esencialmente, lo que estoy haciendo no funciona y me pregunto si alguien puede detectar el motivo.
El modelo $$y=mx+c$$ evaluado en $m=2$ y $c=4$ como un modelo lineal simple:
El algoritmo
- Inicializar $m0$ y $c0$ para que sean valores aleatorios (elegí arbitrariamente 25 para ambos) y evalúo una función que mide la discrepancia entre los datos experimentales y los simulados (donde, por supuesto, en este caso los datos experimentales también se simulan con los parámetros correctos). Utilizo la suma de cuadrados $SSR$ :
$$ SSR=\frac{(SimulatedData-ExperimentalData)^2}{2*sigma^2}$$
Dado que no hay error experimental en este modelo, se eligió arbitrariamente que sigma fuera 0,0001 en todos los casos.
- A continuación, comienzo un bucle y muestreo de anteriores $_m$ y $_c$ , produciendo $m_prop$ y $c_prop$ respectivamente, que se distribuyen uniformemente entre 0 y 100.
- Calcule el $SSR$ con los parámetros muestreados
- Calcular el cociente de probabilidades $LR$ : $$ LR=exp[\frac{(-ln(SSR proposed)+ln(SSR current)}{2*sigma^2}]$$
- Aceptar aleatoriamente los nuevos parámetros mediante un nuevo muestreo de la distribución uniforme entre 0 y 1 (lo llamamos $r$ ). Si $LR>r$ se aceptan los nuevos parámetros y $m_prop$ se convierte en $m0$ y $c_prop$ se convierte en $c0$
Como pregunta al margen, ¿por qué algunos dicen que la probabilidad de aceptación es $min(1,LR)$ mientras que el puesto que estoy siguiendo utiliza la aceptación aleatoria?
- Iterar hasta la convergencia
Resultados
---------edit--------------
Por cortesía de la respuesta de Joriki, he eliminado el $2*sigma^2$ de la función de verosimilitud, de modo que el paso 4 queda así:
- Calcular el cociente de probabilidades $LR$ : $$ LR=exp[(-ln(SSR proposed)+ln(SSR current)]$$
Esto ha mejorado considerablemente los resultados:
Código Matlab
Para completar y dar los detalles del algoritmo, aquí está el código que estoy usando para generar los gráficos:
interval=1:100;
y=mx_plus_c((2),interval,(4));
n=1e5; %iterations
results=zeros(n,8);
m0=25;
c0=25;
y_sim=mx_plus_c(m0,interval,c0);
SSR_cur=SSR(y,y_sim,0.0001);
mlb=log(1); %lb lower bound, ub upper bound respoectively
mub=log(100);
clb=log(1);
cub=log(100);
for i=1:n,
m_prop = (mlb+(mub-mlb).*rand(1,1) ) ;
c_prop = (clb+(cub-clb).*rand(1,1) ) ;
SSR_prop=SSR(y,mx_plus_c(m_prop,interval,c_prop),0.0001);
likelihood_ratio=exp((-log(SSR_prop)+log(SSR_cur)));
r = ( (0+(1-0).*rand(1,1) ) );
if likelihood_ratio>r,
m0=m_prop;
c0=c_prop;
SSR_cur=SSR_prop;
end
results(i,1)=m0;
results(i,2)=c0;
results(i,3)=SSR_cur;
results(i,4)=m_prop;
results(i,5)=c_prop;
results(i,6)=SSR_prop;
results(i,7)=likelihood_ratio;
results(i,8)=r;
end
% results
figure(2)
hist(results(:,1),1000)
title('Distribution of m parameters','fontsize',16)
xlabel('Parameter Values','fontsize',16)
ylabel('Frequency','fontsize',16)
figure(3)
hist(results(:,2),1000)
title('Distribution of c parameters','fontsize',16)
xlabel('Parameter Values','fontsize',16)
ylabel('Frequency','fontsize',16)
Où : mx_plus_c
es una función de Matlab:
function y=mx_plus_c(m,x,c)
y=m*[x]+c;
end
Y SSR
también es una función de Matlab
function chi2 = SSR(sim,exp,sigma)
chi2 =sum( ( ([sim]-[exp]).^2)./ ( 2*sigma^2) ) ;