Ajustando um modelo de mistura gaussiana usando descida de gradiente estocástico

8

Estou trabalhando em um modelo de aprendizado de categoria on-line que usa descida de gradiente estocástico para se ajustar a um modelo de mistura gaussiana. O modelo é baseado no modelo de aprendizado on-line usado em Toscano e McMurray (2010).

Embora a descida do gradiente pareça estar funcionando razoavelmente bem para estimar as médias e frequências / probabilidades de mistura das categorias, estou tendo problemas com a estimativa das covariâncias dos componentes da mistura. As derivadas parciais que tenho usado para a atualização da descida do gradiente vêm de Petersen & Pedersen (2008) (p. 44)

Começando com

p(x)=kρkNx(μk,Σk)

Petersen & Pedersen fornecem a derivada parcial em relação à matriz de covariância comoΣ

δlnp(x)δΣj=ρjNx(μj,Σj)kρkNx(μk,Σk)12[Σj1+Σj1(xμj)(xμj)TΣj1]

A etapa de gradiente de descida para cada , como eu tenho isto implementado em Python é (esta é uma ligeira simplificação ea ô Σ para todos os componentes é calculada antes de realizar a atualização):ΣjΔΣ

j.sigma += learning_rate*(G(x)/M(x))*0.5*(-inv(j.sigma) + inv(j.sigma).dot((x-j.mu).dot((x-j.mu).transpose())).dot(inv(j.sigma)))

jρjNx(μj,Σj)kρkNx(μk,Σk)

Então, eu estou me perguntando se há algo errado com meu código (altamente provável) ou se essa é realmente uma maneira muito ruim de ajustar esse tipo de modelo ao lidar com dados com mais de duas dimensões (consulte Toscano e McMurray para algoritmos univariados). e dados bivariados que definitivamente funcionam).

referências: Toscano, JC e McMurray, B. (2010). Integração de pistas com categorias: ponderação de pistas acústicas na fala usando aprendizado não supervisionado e estatísticas distributivas. Ciência Cognitiva, 34, 434-464.

Petersen & Pederson. The Matrix Cookbook, Versão: 14 de novembro de 2008

phased_chirp
fonte

Respostas:

3

mus[d]μjj.sigmaΣjG(x)/M(x)jx

p(jx)=ρjNx(μj,Σj)kρkNx(μk,Σk),
  • Eu esperaria que o acesso à média, à covariância e ao cálculo da posterior para todos envolvam um jou outro d, qualquer que seja a variável que representa o componente para o qual você deseja calcular o gradiente no seu código. Se você nos o que dizer je drepresentam, poderemos ser capazes de lhe dizer mais.
  • Se G(x)/M(x)acessos j.Sigmapara calcular o posterior, seu código pode não calcular o que você acha que ele faz. Talvez seja melhor calcular primeiro todos os gradientes de todos os parâmetros e executar a atualização.
  • A descida do gradiente estocástico geralmente não é a primeira escolha para otimizar as misturas de gaussianos. Na maioria das vezes, a maximização de expectativas (EM) é usada (ver, por exemplo, Bishop, 2007). Mesmo que você não use o EM, considere o BFGS ou o L-BFGS (implementado em scipy.optimize) antes de usar o SGD. E mesmo se você seguir o SGD, considere usar vários pontos de dados ("lotes") por vez para estimar o gradiente ou, pelo menos, incluir um termo de momento . Analisando brevemente o artigo de Toscano e McMurray, meu palpite é que eles escolheram usar o SGD porque estavam interessados ​​em modelar a aquisição de fala de uma maneira biologicamente mais plausível, em vez de obter o melhor ajuste possível e fazer isso on-line (ou seja, um dado ponto de cada vez). Se você não precisar disso, meu conselho seria usar o EM.

    (Acabei de perceber que você pediu especificamente para o aprendizado on-line , portanto, a única opção viável para você é adicionar o termo de momento para acelerar um pouco as coisas.)

  • A maneira como você escolheu calcular o gradiente é bastante ineficiente, o que desacelerará ainda mais o aprendizado. Você pode não ter visto resultados razoáveis ​​porque leva uma eternidade para o algoritmo convergir para algo interessante. Aqui está uma maneira um pouco melhor para calcular o gradiente:

    sigmaInv = inv(j.sigma)
    dSigma = G(x)/M(x) * 0.5 * (-sigmaInv + numpy.sum(sigmaInv.dot(x - mus[d]) * x))

    Σj

Lucas
fonte
Obrigado pelas sugestões @ Lucas. Desculpe pelo código pouco claro. É parte de uma função maior que reescrevi para que fizesse um pouco mais de sentido por si só. O SigmaInv é calculado apenas uma vez e todos os gradientes são calculados antes da atualização. Isso precisa ser um modelo on-line para o que estou fazendo, portanto não posso usar o EM. Eu tentei uma versão um pouco diferente, que usa a fatoração de Sigma de Cholesky, mas se comportou de maneira um pouco estranha.
phased_chirp