domingo, 20 de março de 2022

Gaussian Mixture Models - Parte III

No último post implementamos um algoritmo EM para estimar os parâmetros do modelo de mistura de duas distribuições Gaussianas. Hoje vamos ver o modelo de mistura com $m$ distribuições Gaussianas.

Modelo

Seja $X$ a variável de interesse. Considere que os dados possam ser originados de $m$ distribuições Gaussianas. A função de densidade do modelo é dada por

\begin{eqnarray} f(x) = \sum_{j=1}^m p_j f(x|\theta_j), \nonumber \end{eqnarray}

em que $\theta_j = (\mu_j,\sigma^2_j)$ e $p_j$ são os parâmetros e o peso da $j$-ésima distribuição, respectivamente. Considerando $Y_i$ como a variável que indica a que distribuição $X_i$ pertence e dada uma amostra aleatória, a função de log-verossimilhança do modelo completo será

\begin{eqnarray} l(\theta) = \log \prod_{i=1}^n f(x_i,y_i) = \sum_{i=1}^n \sum_{y_i \in C} 1\{y_i = c\} \big[ \log(p_{y_i}) + \log(f(x_i|\theta_{y_i})) \big], \nonumber \end{eqnarray}

em que $C = \{1,2,...,m\}$.

Algoritmo EM

Passo E

A função $Q$ será dada por

\begin{eqnarray} Q(\theta|\theta^{(k)}) = \sum_{i=1}^n \sum_{y_i \in C} \gamma_{ic} \big[ \log(p_{y_i}) + \log(f(x_i|\theta_{y_i})) \big], \nonumber \end{eqnarray}

em que

\begin{eqnarray} \gamma_{ic} = E[1\{y_i = c\}|x_i,\theta^{(k)}] = P(Y_i = c | x_i) = \dfrac{p_c f(x_i|\theta_c)}{\sum_{j=1}^m p_j f(x_i|\theta_j)}. \nonumber \end{eqnarray}

Passo M

Maximizando a função $Q$, encontramos os seguintes estimadores para os parâmetros:

\begin{eqnarray} \hat{\mu}_j &=& \dfrac{\sum_{i=1}^n (\gamma_{ij}x_i)}{\sum_{i=1}^n \gamma_{ij}}, \nonumber \\ \hat{\sigma}^2_j &=& \dfrac{\sum_{i=1}^n \gamma_{ij}(x_i-\mu_i)^2}{\sum_{i=1}^n \gamma_{ij}}, \nonumber \\ \hat{p}_j &=& (1-\sum_{k=1,k\neq j}^{m-1}p_k)\dfrac{\sum_{i=1}^n \gamma_{ij}}{\sum_{i=1}^n (\gamma_{ij}+\gamma_{im})}, \nonumber \\ \hat{p}_m &=& 1 - \hat{p}_1 - \hat{p}_2 -...-\hat{p}_{m-1}. \nonumber \end{eqnarray}

Implementando o algoritmo

Agora, vamos implementar um algoritmo que recebe do usuário os dados, o número de distribuições Gaussianas que será assumido, o vetor de valores iniciais para os parâmetros, o número máximo de iterações e o critério de parada do algoritmo EM (diferença máxima permitida entre duas estimações). Para isso, vamos assumir que o vetor de parâmetros possui o seguinte padrão: $\theta = (\mu_1,...,\mu_m,\sigma^2_1,...,\sigma^2_m,p_1,...,p_{m-1})$. Perceba que o tamanho do vetor $\theta$ deve ser $3m-1$.

Abaixo mostro como fica o algoritmo. Como fizemos passo a passo a implementação para duas distribuições no post anterior, explicarei apenas as principais mudanças.

set.seed(7)
GMM_EM = function(x,m,theta_ini,max_ite=100,dif_parada=10^-3){
  
  npar = length(theta_ini);
  
  n = length(x)
  if(length(theta_ini)!=(3*m-1)){
    cat("Tamanho do vetor de valores iniciais deve ser 3m -1, em que m é o 
        número de distribuições consideradas.\n");
    return();
  }
  
  gamaic = matrix(nrow=n,ncol=m);
  
  theta.curr = theta_ini;
  theta.trace = matrix(nrow=1,ncol=length(theta.curr));
  theta.trace[1,] = theta.curr;
  mu.hat = matrix(nrow=1,ncol=m);
  sigma2.hat = matrix(nrow=1,ncol=m);
  p.hat = matrix(nrow=1,ncol=(m-1));
  
  indm = 1;
  inds = m+1;
  indp = 2*m+1;
  
  atingiu_maxit = TRUE;
  parada = matrix(0,ncol=npar,nrow=1); #menor que o erro
  
  for(cont in 1:max_ite){
    #PASSO E - CALCULO DE GAMMAIC
    
    pm = 1 - sum(theta.curr[indp:(3*m-1)])
    for(i in 1:n){
      d = matrix(nrow=1,ncol=m);
      for(j in 0:(m-2)){
        d[1,(j+1)] = theta.curr[indp+j]*dnorm(x[i],mean=theta.curr[indm+j],
                                              sd=sqrt(theta.curr[inds+j]));
      }
      d[1,m] = pm*dnorm(x[i],mean=theta.curr[m],sd=sqrt(theta.curr[2*m]));
      denom = sum(d);
      for(j in 1:m) gamaic[i,j] = d[1,j]/denom;
    }
    
    #PASSO M - ESTIMACAO
    for(j in 1:m){
      sg = sum(gamaic[,j]);
      mu.hat[1,j] = sum(gamaic[,j]*x)/sg;
      delta = (x-mu.hat[1,j])^2;
      sigma2.hat[1,j] = sum(gamaic[,j]*delta)/sg;
    }
    sgm = sum(gamaic[,m]);
    aux = theta.curr[indp:(3*m-1)];
    for(j in 1:(m-1)){
      sp = 1 - sum(aux[-j]);
      sg = sum(gamaic[,j]);
      p.hat[1,j] = sp* sg/(sg+sgm);
    } 
    
    theta.curr = c(mu.hat[1,],sigma2.hat[1,],p.hat[1,]);
    theta.trace = rbind(theta.trace,theta.curr);
    
    dif = abs(theta.trace[cont+1,]-theta.trace[cont,])
    for(j in 1:npar) {
      if(dif[j] < dif_parada) {
        parada[j] = 1;
      }else{
        parada[j] = 0;
      }
    }
    
    if(sum(parada)==npar) {
      cat("Algoritmo convergiu com",cont,"iterações.\n")
      atingiu_maxit=FALSE;
      break;
    }
    
  }
  
  if(atingiu_maxit==T) cat("Algoritmo atingiu número máximo de iterações.\n")
  
  return(theta.trace);
}

Vamos às principais alterações:

  • Verificamos se o tamanho do vetor de valores iniciais corresponde ao número de distribuições informado.
  if(length(theta_ini)!=(3*m-1)){
    cat("Tamanho do vetor de valores iniciais deve ser 3m -1, em que m é o 
        número de distribuições consideradas.\n");
    return();
  }
  • Como os parâmetros estão em apenas um vetor (theta.curr), armazenamos as posições do vetor em que cada conjunto de parâmetros começa, isto é, os parâmetros de média começam em [1], os de variância em [m+1] e os de peso em [2*m+1].
  indm = 1;
  inds = m+1;
  indp = 2*m+1;
  • Os passos E e M condizem com as fórmulas do começo do post. Deixo para você interpretá-las.
  • A parada do algoritmo ocorre quando a diferença da estimação de cada parâmetro entre a iteração atual e a anterior é menor que o critério fornecido (dif_parada).
    dif = abs(theta.trace[cont+1,]-theta.trace[cont,])
    print(round(dif,4));
    for(j in 1:npar) {
      if(dif[j] < dif_parada) {
        parada[j] = 1;
      }else{
        parada[j] = 0;
      }
    }
    
    if(sum(parada)==npar) {
      cat("Algoritmo convergiu com",cont,"iterações.\n")
      atingiu_maxit=FALSE;
      break;
    }

Vamos testar o algoritmo acima com os mesmos dados do post anterior: duas distribuições.

set.seed(7)
x = c(rnorm(50,mean=-2,sd=1),rnorm(50,mean=2,sd=1))

theta_ini = c(-1,1,10,1,.2);
max_ite = 100;
m=2;

> res = GMM_EM(x,m,theta_ini,max_ite,dif_parada = 10^-4);
Algoritmo convergiu com 20 iterações.

Perceba que o algoritmo convergiu em um número de iterações bem menor que o máximo fornecido. Utilizar critério de parada pode nos ajudar a poupar tempo, tanto computacional quanto nosso próprio tempo. Lembre-se disso!

O gráfico abaixo apresenta a trajetória das estimativas dos parâmetros. Como utilizamos os mesmos valores iniciais do post anterior, obtemos o mesmo gráfico. Porém, agora com menos iterações devido ao critério de parada. 


Note que, nesse caso, sabemos exatamente de quantas distribuições os dados foram originados. Suponha agora que não sabemos e informamos o número "errado" de distribuições. O que aconteceria? Vamos testar:

theta_ini = c(-1,1,5,10,1,3,.5,.1);
max_ite = 500;
m=3;

> res = GMM_EM(x,m,theta_ini,max_ite,dif_parada = 10^-4);
Algoritmo convergiu com 488 iterações.

Observe que, dessa vez, o algoritmo demorou mais para convergir. O resultado é apresentado abaixo:



> res[489,] #mu1 mu2 mu3 sigma2.1 sigma2.2 sigma2.3 p1 p2
[1] -1.99194446  1.74776537  2.45300571  0.61822279  1.20592365  0.06526058
[7]  0.44328369  0.48841668
> 1-res[489,7]-res[489,8] #p3
theta.curr 
0.06829962 

Note que, apesar de o algoritmo encontrar uma terceira distribuição com média 2.45, o peso dessa distribuição é bem próximo de zero. Isso indica que, apesar de assumirmos que há três distribuições, apenas duas são relevantes com mais de 90% de peso. Essas duas distribuições são bem próximas das que geramos os dados, ou seja, temos uma boa estimativa mesmo considerando três distribuições.

Agora temos um algoritmo para estimar os parâmetros do modelo de mistura de normais para um número genérico de distribuições. Incrível, não?

Espero que tenha gostado da aula.

Até a próxima aula!

quinta-feira, 17 de março de 2022

Gaussian Mixture Models - Parte II

No post anterior, vimos o modelo de mistura de distribuições normais e fizemos um exemplo considerando duas distribuições Gaussianas. Vimos também que não há forma fechada para os EMVs dos parâmetros do modelo e recorremos ao modelo aumentado, incorporando uma variável latente para indicar de qual distribuição uma determinada observação é originada. Nesse contexto, utilizamos o algoritmo EM para estimar os parâmetros do modelo.

No post de hoje, vamos implementar o algoritmo de estimação para nosso exemplo utilizando o R. Como motivação, vamos simular dados de duas distribuições Gaussianas, a primeira com média -2 e a segunda com média 2, ambas com variância 1. A figura abaixo apresenta o histograma de 100 observações, sendo metade dos dados de cada distribuição.

set.seed(7)
x = c(rnorm(50,mean=-2,sd=1),rnorm(50,mean=2,sd=1))
par(mar=c(2,4,.5,.5))
hist(x,main='',xlab='')



Para começar nosso código, vamos definir alguns objetos.

n = length(x)

gamaic = matrix(nrow=n,ncol=2);

#theta = (mu1,mu2,sigma2.1,sigma2.2,p1)
theta.curr = c(1,1,10,1,.2)
theta.trace = matrix(nrow=1,ncol=length(theta.curr));
theta.trace[1,] = theta.curr

max_ite = 100;

O que fizemos:

  1. Computamos o tamanho da amostra,
  2. Criamos uma matriz para conter todos os valores de $\gamma_{ic} = P(Y_i = c|x_i)$.
  3. Computamos valores iniciais para o vetor de parâmetros $(\mu_1,\mu_2,\sigma^2_1,\sigma^2_2,p_1)$.
  4. Criamos uma matriz para armazenar a trajetória dos parâmetros.
  5. Colocamos os valores iniciais na primeira linha da matriz de trajetórias.
  6. Definimos o número máximo de iterações do algoritmo como 100.

Nosso algoritmo é iterativo, logo deve estar dentro de uma estrutura de repetição:

for(j in 1:max_ite){
  (...)
}

Vamos começar a programar nosso método de estimação. Primeiro vamos armazenar os valores de theta.curr em variáveis com os nomes dos parâmetros para o código ficar mais legível (mas não é necessário).

mu1 = theta.curr[1];
mu2 = theta.curr[2];
sigma2.1 = theta.curr[3];
sigma2.2 = theta.curr[4];
p1 = theta.curr[5];
p2 = 1-p1;

Agora, vamos implementar o passo E. Nesse passo, temos que calcular os valores de $\gamma_{ic}$ dados os valores de $x$ e $\theta^{(j-1)}$.

#PASSO E - CALCULO DE GAMMAIC

for(i in 1:n){
  d1 = p1*dnorm(x[i],mean=mu1,sd=sqrt(sigma2.1));
  d2 = p2*dnorm(x[i],mean=mu2,sd=sqrt(sigma2.2));

  gamaic[i,1] = d1/(d1+d2);
  gamaic[i,2] = d2/(d1+d2);
}

Agora, dados os valores de $\gamma_{ic}$, vamos maximizar a função $Q$ e estimar os parâmetros (passo M), calculando as estimativas dos parâmetros.

#PASSO M - ESTIMACAO

sg1 = sum(gamaic[,1]);
sg2 = sum(gamaic[,2]);

mu1.hat = sum(gamaic[,1]*x)/sg1;
mu2.hat = sum(gamaic[,2]*x)/sg2;
delta = (x-mu1.hat)^2;
sigma2.1.hat = sum(gamaic[,1]*delta)/sg1;
delta = (x-mu2.hat)^2;
sigma2.2.hat = sum(gamaic[,2]*delta)/sg2;
p1.hat = sg1/(sg1+sg2);

Com as novas estimativas dos parâmetros, precisamos atualizar o vetor theta.curr e armazenar essas estimativas na matriz de trajetórias.

theta.curr = c(mu1.hat,mu2.hat,sigma2.1.hat,sigma2.2.hat,p1.hat)
theta.trace = rbind(theta.trace,theta.curr);

O algoritmo está pronto. Mas temos que executar todo o bloco de código cada vez que quisermos realizar a estimação. Dessa forma, o código abaixo apresenta o algoritmo dentro de uma função.

GMM_EM = function(x,theta_ini,max_ite){
    
    n = length(x)
    
    gamaic = matrix(nrow=n,ncol=2);
    
    theta.curr = theta_ini;
    theta.trace = matrix(nrow=1,ncol=length(theta.curr));
    theta.trace[1,] = theta.curr
    
    for(j in 1:max_ite){
    
        mu1 = theta.curr[1];
        mu2 = theta.curr[2];
        sigma2.1 = theta.curr[3];
        sigma2.2 = theta.curr[4];
        p1 = theta.curr[5];
        p2 = 1-p1;
        
        #PASSO E - CALCULO DE GAMMAIC
        
        for(i in 1:n){
          d1 = p1*dnorm(x[i],mean=mu1,sd=sqrt(sigma2.1));
          d2 = p2*dnorm(x[i],mean=mu2,sd=sqrt(sigma2.2));
        
          gamaic[i,1] = d1/(d1+d2);
          gamaic[i,2] = d2/(d1+d2);
        }
        
        #PASSO M - ESTIMACAO
        
        sg1 = sum(gamaic[,1]);
        sg2 = sum(gamaic[,2]);
        
        mu1.hat = sum(gamaic[,1]*x)/sg1;
        mu2.hat = sum(gamaic[,2]*x)/sg2;
        delta = (x-mu1.hat)^2;
        sigma2.1.hat = sum(gamaic[,1]*delta)/sg1;
        delta = (x-mu2.hat)^2;
        sigma2.2.hat = sum(gamaic[,2]*delta)/sg2;
        p1.hat = sg1/(sg1+sg2);

        theta.curr = c(mu1.hat,mu2.hat,sigma2.1.hat,sigma2.2.hat,p1.hat)
        theta.trace = rbind(theta.trace,theta.curr);
    }
    return(theta.trace);
}

Vamos testar nosso código com os dados que geramos inicialmente.

set.seed(7)
x = c(rnorm(50,mean=-2,sd=1),rnorm(50,mean=2,sd=1))

theta_ini = c(1,1,10,1,.2);
max_ite = 100;
res = GMM_EM(x,theta_ini,max_ite);

>head(res);
                [,1]     [,2]      [,3]     [,4]      [,5]
            1.000000 1.000000 10.000000 1.000000 0.2000000
theta.curr -1.139293 1.070248  4.817979 2.227314 0.4216040
theta.curr -1.194942 1.261527  3.356893 2.722751 0.4570911
theta.curr -1.313885 1.418818  2.698869 2.608024 0.4684452
theta.curr -1.477107 1.584125  2.149425 2.196990 0.4721721
theta.curr -1.655599 1.751241  1.567991 1.660437 0.4733255

Agora vamos plotar os gráficos com as trajetórias das estimativas dos parâmetros.

par(mfrow=c(2,3))
plot(res[,1],type='l',main=expression(mu[1])); abline(h=-2,col='blue');
plot(res[,2],type='l',main=expression(mu[2])); abline(h=2,col='blue');
plot(res[,3],type='l',main=expression(sigma[1]^2 )); abline(h=1,col='blue');
plot(res[,4],type='l',main=expression(sigma[2]^2 )); abline(h=1,col='blue');
plot(res[,5],type='l',main=expression(p[1])); abline(h=0.5,col='blue');



O valor da estimativa dos parâmetros é a última linha da matriz de trajetórias, ou seja, a última estimativa fornecida pelo algoritmo. Dessa forma, temos

>res[(max_ite+1),] #mu1 mu2 sigma2.1 sigma2.2 p1
[1] -1.9704849  1.8669399  0.6421497  1.0473874  0.4503654

>1 - res[(max_ite+1),5]  #p2
0.5496346

Agora temos um algoritmo para estimar os parâmetros do modelo de misturas de duas distribuições Gaussianas! Incrível, não acha?

Porém, há um problema que precisamos discutir. O que aconteceria se assumíssemos valores iniciais iguais para os parâmetros das duas distribuições? Vamos testar.

theta_ini = c(1,1,1,1,.2); 
max_ite = 100;
res = GMM_EM(x,theta_ini,max_ite);

> head(res);
                [,1]      [,2]     [,3]     [,4] [,5]
           1.0000000 1.0000000 1.000000 1.000000  0.2
theta.curr 0.1386966 0.1386966 4.510061 4.510061  0.2
theta.curr 0.1386966 0.1386966 4.510061 4.510061  0.2
theta.curr 0.1386966 0.1386966 4.510061 4.510061  0.2
theta.curr 0.1386966 0.1386966 4.510061 4.510061  0.2
theta.curr 0.1386966 0.1386966 4.510061 4.510061  0.2

Observe que a estimativa de $p_1$ não se altera e, após a primeira iteração, as estimativas dos demais parâmetros permanecem constantes. Por que isso ocorre? Observe que assumimos $\mu_1^{(0)} = \mu_2^{(0)}$ e $(\sigma^2_1)^{(0)} = (\sigma^2_2)^{(0)}$ e ,como consequência, $f(x_i|\theta_1) = f(x_i|\theta_2)$. Dessa forma, $\gamma_{i1} = p_1^{(0)}$ e $\gamma_{i2} = p_2^{(0)}$ e, como consequência,

\begin{eqnarray} \hat{\mu}_1 = \hat{\mu}_2 &=& \dfrac{\sum_{i-1}^{n} x_i}{n}, \nonumber\\ \hat{\sigma}^2_1 = \hat{\sigma}^2_2 &=& \dfrac{\sum_{i-1}^{n}(x_i-\hat{\mu}_1)^2}{n}, \nonumber\\ \hat{p}_1 &=& p_1^{(0)}. \nonumber \end{eqnarray}

Logo, para que o algoritmo funcione, precisamos assumir valores iniciais distintos para as distribuições. Se consideramos mesma média, devemos assumir variâncias diferentes e vice-versa.

Na próxima aula vamos expandir a ideia do modelo para uma mistura de $n$ distribuições Gaussianas.

Espero que tenha gostado da aula.

Até a próxima aula!

terça-feira, 15 de março de 2022

Gaussian Mixture Models - Parte I

Normalmente utilizamos uma determinada distribuição para modelar dados. Escolhida uma distribuição para a modelagem, precisamos estimar seus parâmetros por algum método de estimação. Por exemplo, se estamos trabalhando com a distribuição normal, é de interesse estimar os parâmetros $\mu$ e $\sigma^2$, que são a média e a variância da distribuição. Note que, nesse caso, supomos que os dados são originados de uma distribuição apenas.

Mas e se os dados vierem de duas ou mais distribuições? Confuso? Imagine clusters (ou agrupamentos), como na figura abaixo. Percebemos que uma parte dos dados parecem ser originados de uma distribuição e a outra parte, de outra distribuição. Os dados observados (representados pelo histograma) contemplam os dados das duas distribuições mas, na prática, não sabemos quais são (ou quantas são). Dessa forma, a modelagem de mistura de distribuições se torna bastante útil.



Nesse post, ensino como trabalhar com mistura de distribuições Gaussianas, ou seja, quando os dados pertencem a mais de uma distribuição normal (médias e/ou variâncias distintas). Para a estimação dos parâmetros, utilizaremos o algoritmo EM (já explicado aqui no blog).

Gaussian Mixture Models

Para começarmos, vamos supor que nossos dados sejam provenientes de duas distribuições Gaussianas com parâmetros desconhecidos. Seja $X$ nossa variável de interesse. A função de densidade do modelo é dada por

$$\begin{eqnarray}\label{eq:model} f(x|\theta) = p_1f(x|\theta_1) + p_2f(x|\theta_2) \end{eqnarray}$$

em que $\theta_1 = (\mu_1,\sigma^2_1)$ e $\theta_2 = (\mu_2,\sigma^2_2)$ são os vetores de parâmetros das distribuições normais 1 e 2, respectivamente, e $p_1$ e $p_2$ são os pesos relacionados a ambas distribuições. Podemos interpretar os pesos como as probabilidades de uma observação ser proveniente de uma determinada distribuição, ou seja, $p_1$ é a probabilidade dessa observação pertencer à distribuição 1 e $p_2$, a probabilidade dela pertencer à distribuição 2. O vetor de parâmetros do modelo é $\theta = (\theta_1,\theta_2,p_1)$. Por que apenas $p_1$? Porque $p_2$ é completamente determinada por $p_1$, isto é, $p_2 = 1 - p_1$.

Seja $X_1, X_2, ..., X_n$ uma amostra aleatória da distribuição em ($\ref{eq:model}$). A função de log-verossimilhança do modelo é dada por

$$\begin{eqnarray} l(\theta) &=& \log \left[ \prod_{i=1}^n f(x_i|\theta) \right] = \sum_{i=1}^n \log f(x_i|\theta) = \sum_{i=1}^n \log \big[ p_1 f(x_i|\theta_1) + p_2 f(x_2|\theta_2) \big]\end{eqnarray}$$

Se prosseguirmos para encontrar os estimadores de máxima verossimilhança (EMV) a partir da função acima, veremos que não há forma fechada para os estimadores. Logo, outra abordagem é necessária.

Modelo aumentado

Para isso, imagine que para cada observação $x_i$ conhecemos a qual distribuição ela pertence. Isso é equivalente a dizer que conhecemos uma variável $Y_i$ que indica se a observação $x_i$ pertence a distribuição $C$, $C = 1,2$. A função de densidade de $Y_i$ é dada por

$$f(y_i) = \prod_{y_i \in C} p_{y_i}^{1 \{y_i = c\}}, \quad C = \{1,2\}$$

em que $1\{\}$ é a função indicadora. Dado o valor de $y_i$, a função de densidade de $X_i$ será

$$f(x_i|y_i) = \prod_{y_i \in C} f(x_i|\theta_{y_i})^{1\{y_i = c\}}$$

Na prática não observamos os valores de $Y_i$. Dessa forma, $Y_i$ é uma variável latente e trabalhamos com o modelo aumentado $(X,Y)$. A função de densidade conjunta de $(X_i,Y_i)$ é dada por

\begin{eqnarray}
f(x_i,y_i) &=& f(x_i|y_i) f(y_i)  = \prod_{y_i \in C} \left( p_{y_i} f(x_i|\theta_{y_i}) \right)^{1\{y_i = c\}} \nonumber
\end{eqnarray}

A função de verossimilhança do modelo aumentado, dada uma amostra aleatória $(X,Y) = ((X_1,Y_1),...,(X_n,Y_n))$, será 

\begin{eqnarray}
L(\theta) &=& \prod_{i=1}^n f(x_i|y_i) f(y_i)  = \prod_{i=1}^n \left[ \prod_{y_i \in C} \left( p_{y_i} f(x_i|\theta_{y_i}) \right)^{1\{y_i = c\}} \right] \nonumber
\end{eqnarray}

e a função de log-verossimilhança é dada por 

\begin{eqnarray}
l(\theta) &=& \sum_{i=1}^n  \sum_{y_i \in C} {1\{y_i = c\}} \left[ \log (p_{y_i}) + \log (f(x_i|\theta_{y_i}))  \right]  \nonumber
\end{eqnarray}

Vamos refletir um pouco sobre o que nós fizemos. 

  • Primeiro modelamos o problema e chegamos na função de verossimilhança em (\ref{eq:model}).
  • Percebemos que não há como estimar os parâmetros do modelo dessa forma e outra abordagem se tornou necessária.
  • Consideramos uma variável $Y$ para indicar em que grupo (cluster) a variável $X$ pertence.
  • Escrevemos o modelo completo para $(X,Y)$.

Observe que $X$ é variável observada, enquanto que $Y$ é não observada (latente). Dessa forma, precisamos de um método para estimar os parâmetros do modelo nesse contexto. Como falamos no começo do post, utilizaremos o algoritmo EM. Mas por quê? Se você acompanha o blog, já deve saber a resposta.

Temos um modelo com variáveis observadas e variáveis não observadas. O algoritmo EM é excelente no contexto de dados faltantes, em que a função de verossimilhança completa é mais simples de se trabalhar do que a função de verossimilhança dos dados observados. Dessa forma, vamos prosseguir para a estimação dos parâmetros.

Estimação dos parâmetros - Algoritmo EM

Passo E

A função $Q$ será dada por

\begin{eqnarray}
Q(\theta|\theta^{(k)}) &=& \sum_{i=1}^n  \sum_{y_i \in C} E[{1\{y_i = c\}}|x,\theta_{(k)}] \left[ \log (p_{y_i}) + \log (f(x_i|\theta_{y_i}))  \right]  \nonumber
\end{eqnarray}

Para facilitar a notação, escrevemos $\gamma_{ic} =  E[{1\{y_i = c\}}|x,\theta_{(k)}] $. Note que $\gamma_{ic}$ é a probabilidade de $Y_i$ ser igual a $c$ (ou seja, indicar que $x_i$ pertence a distribuição $c$) dado o valor de $x_i$. Ou seja, 

\begin{eqnarray} \gamma_{ic} = P(Y_i = c|x_i) = f(y_i = c|x_i) \nonumber \end{eqnarray}

Para calcularmos o valor de $\gamma_{ic}$, precisamos encontrar a distribuição de $Y_i|X_i$. Temos então

\begin{eqnarray}
f(y_i|x_i) &=& \dfrac{f(x_i|y_i)f(y_i)}{f(x_i)} = \dfrac{\prod_{y_i \in C} \left[p_{y_i}f(x_i|\theta_{y_i}) \right] ^{1\{y_i = c\}}}{p_{1}f(x_i|\theta_{1})+p_{2}f(x_i|\theta_{2})}  \nonumber
\end{eqnarray}

Dessa forma,

\begin{eqnarray} \gamma_{ic} &=& P(Y_i = c|x_i)  = \dfrac{p_{c}f(x_i|\theta_{c}) }{p_{1}f(x_i|\theta_{1})+p_{2}f(x_i|\theta_{2})} \nonumber \end{eqnarray}

Passo M

Para encontrar os estimadores, precisamos derivar a função $Q()$ em relação aos parâmetros de interesse. Vamos realizar primeiro a estimação de $\mu_1$:

\begin{eqnarray}
\dfrac{d}{d\mu_1}Q()  &=&\sum_{i=1}^{n} \gamma_{i1}  \dfrac{d}{d\mu_1} \log f(x_i|\theta_1) = \sum_{i=1}{n} \gamma_{i1}  \dfrac{(x_i-\mu_1)}{\sigma^2_1} \nonumber
\end{eqnarray}

Igualando $(d/d\mu_1)Q()$ a zero, obtemos $\hat{\mu}_1 = \dfrac{\sum_{i=1}^n (\gamma_{i1} x_i)}{\sum_{i=1}^n \gamma_{i1}}$.

De forma análoga, $\hat{\mu}_2 = \dfrac{\sum_{i=1}^n (\gamma_{i2} x_i)}{\sum_{i=1}^n \gamma_{i2}}$

Em relação à variância da distribuição 1, $\sigma^2_1$, temos

\begin{eqnarray}
\dfrac{d}{d\sigma^2_1}Q()  &=&\sum_{i=1}{n} \gamma_{i1}  \left(\dfrac{-1}{2\sigma^2_1} + \dfrac{1}{2\sigma^4_1}(x_i-\mu_1)^2 \right)\nonumber \\
\end{eqnarray}

Igualando $(d/d\sigma^2_1)Q()$ a zero, obtemos $\hat{\sigma}^2_1 = \dfrac{\sum_{i=1}^n \gamma_{i1}(x_i-\mu_1)^2 }{\sum_{i=1}^n \gamma_{i1}}$.

De forma análoga, $\hat{\sigma}^2_2 = \dfrac{\sum_{i=1}^n \gamma_{i2}(x_i-\mu_2)^2 }{\sum_{i=1}^n \gamma_{i2}}$.

Em relação aos pesos $p_1$ e $p_2$, temos que lembrar que

$$p_1 + p_2 = 1 \rightarrow p_2 = 1 - p_1$$

Dessa forma, vamos encontrar o estimador de $p_1$.

\begin{eqnarray}
\dfrac{d}{d p_1}Q()  &=&\sum_{i=1}^{n} \left( \gamma_{i1}  \dfrac{1}{p_1} - \gamma_{i2} \dfrac{1}{1-p_1} \right) \nonumber 
\end{eqnarray}

Igualando $(d/dp_1)Q()$ a zero, obtemos $\hat{p}_1 = \dfrac{\sum_{i=1}^n \gamma_{i1} }{\sum_{i=1}^n (\gamma_{i1}+\gamma_{i2})}$.

Logo, o estimador para $p_2$ é $\hat{p}_2 = 1 - \hat{p}_1$.

Dessa forma, encontramos uma metodologia para estimar os parâmetros da distribuição de mistura de normais. A implementação deste exemplo será feita no próximo post.

Espero que tenha gostado da aula.

Até a próxima aula!