Parametrik olmayan kümeleme için PyMC: Gauss karışımının parametrelerini tahmin etmek için Dirichlet işlemi kümelenemiyor


10

Sorun kurulumu

PyMC'yi uygulamak istediğim ilk oyuncak sorunlarından biri parametrik olmayan kümelenmedir: bazı veriler verildiğinde, Gauss karışımı olarak modelleyin ve kümelerin sayısını ve her kümenin ortalamasını ve kovaryansını öğrenin. Bu yöntem hakkında bildiklerimin çoğu, Michael Jordan ve Yee Whye Teh'in 2007'den beri (seyreklik öfke haline gelmeden önce) ve son birkaç günün Dr Fonnesbeck ve E. Chen'in öğreticilerini [fn1] okuması [ fn2]. Ancak sorun iyi çalışılmıştır ve bazı güvenilir uygulamaları vardır [fn3].

Bu oyuncak probleminde, bir boyutlu Gauss den on çekiliş ve . Aşağıda görebileceğiniz gibi, hangi numunelerin hangi karışım bileşeninden geldiğini anlatmayı kolaylaştırmak için çizimleri karıştırmadım.N ( μ = 4 , σ = 2 )N(μ=0,σ=1)N(μ=4,σ=2)

Gauss karışım modeli verileri

Her veri örneğini , için ve burada bu veri noktası için gösteriyor : . burada kullanılan kesilmiş Dirichlet işleminin uzunluğu: benim için .i = 1 , . . . , 50 Z ı ı z i[ 1 , . . . , N D P ] N D P N D P = 50yiN(μzi,σzi)i=1,...,50ziizi[1,...,NDP]NDPNDP=50

Dirichlet işlem alt yapısını genişletilmesi, her : Küme ID, olasılık yoğunluk fonksiyonu çubuk kıran bir yapı ile verilir kategorik rastgele değişken bir çekme olduğu ile bir için konsantrasyon parametresi . Yapıları Çubuk kıran -uzun vektör ilk elde ederek, 1 Özetle gerekir, o bağlıdır çizer Beta dağıtılmış IID , [fn1] bkz. Verilere bilgisizliğimi bildirmek istediğim için [fn1] 'i takip ediyorum ve varsayıyorum .ziziCategorical(p)pStick(α)αNDPpNDPαααUniform(0.3,100)

Bu, her bir veri örneğinin küme kimliğinin nasıl oluşturulacağını belirtir. Her biri, kümeleri ilişkili bir ortalama ve standart sapma, var ve . Ardından, ve .NDPμziσziμziN(μ=0,σ=50)σziUniform(0,100)

(Daha önce [fn1] düşünülmeksizin, aşağıdaki ve bir hyperprior yerleştirilmesi edildi , olduğu, ile A kendisi bir çekme sabit parametreli normal dağılım ve bir üniformadan . Ancak https://stats.stackexchange.com/a/71932/31187 uyarınca verilerim bu tür hiyerarşik hiper prior'u desteklemez.)μziμziN(μ0,σ0)μ0σ0

Özetle, modelim:

iyiN(μzi,σzi) 1 ila 50 (veri numunelerinin sayısı) kadar devam eder.i

N D P - 1 = 49 p S t i c k ( α ) N D P α U n i f o r m ( 0,3 , 100 )ziCategorical(p) ve 0 ile arasındaki değerleri alabilir ; , bir -uzun vektör; ve , bir skaler. (Şimdi veri örnekleri sayısını daha önce Dirichlet'in kesik uzunluğuna eşit yapmaktan biraz pişmanım, ama umarım açıktır.)NDP1=49pStick(α)NDPαUniform(0.3,100)

μziN(μ=0,σ=50) ve . Orada Bu ortalama ve standart sapmalar (her biri için bir tane olmak mümkün kümeleri.)σziUniform(0,100)NDPNDP

İşte grafik modeli: isimler değişken isimlerdir, aşağıdaki kod bölümüne bakın.

grafik

Sorun bildirimi

Birkaç ince ayar ve başarısız düzeltmeye rağmen, öğrenilen parametreler verileri oluşturan gerçek değerlere hiç benzemez.

Şu anda, rastgele değişkenlerin çoğunu sabit değerlere başlatıyorum. Ortalama ve standart sapma değişkenleri beklenen değerlerine göre başlatılır (yani normal olanlar için 0, eşit olanlar için desteklerinin ortası). Tüm küme kimliklerini 0 olarak başlatırım. konsantrasyon parametresini başlatırım .ziα=5

Bu başlatmalarla 100.000 MCMC yinelemesi ikinci bir kümeyi bulamaz. ilk elemanı 1'e yakındır ve tüm veri örnekleri için hemen hemen in tüm çizimleri . Burada ilk yirmi veri örneği için her 100. çekilişi gösteririm, yani, için :pμziiμzii=1,...,20

Sıfırla başlatılmış küme kimliğine sahip araçlar

İlk on veri örneğinin bir moddan ve geri kalanının diğerinden olduğunu hatırlatarak, yukarıdaki sonuç bunu yakalayamamaktadır.

Küme kimliklerinin rasgele başlatılmasına izin verirseniz, birden fazla küme elde ederim, ancak küme aynı 3.5 düzeyinde dolaşır demektir:

Rastgele başlatılan küme kimliğine sahip araçlar

Bu bana MCMC ile ilgili olağan problemin olduğunu, bulunduğu yerden posteriorun başka bir moduna erişemediğini gösteriyor: bu farklı sonuçların , küme kimliklerinin başlatılmasını değiştirdikten sonra, yalnızca önceliklerini veya başka herhangi bir şey.zi

Herhangi bir modelleme hatası yapıyor muyum? Benzer soru: https://stackoverflow.com/q/19114790/500207 bir Dirichlet dağıtımı kullanmak ve 3 elementli bir Gauss karışımı oluşturmak istiyor ve benzer problemlerle karşılaşıyor. Tamamen eşlenik bir model oluşturmayı ve bu tür kümeleme için Gibbs örneklemeyi kullanmayı düşünmeli miyim? (Parametrik Dirichlet dağıtım durumu için, gün içinde sabit bir konsantrasyon kullanmak dışında bir Gibbs örnekleyicisi uyguladım ve iyi çalıştı, bu yüzden PyMC'nin en azından bu sorunu en azından kolayca çözebilmesini bekleyin.)α

Ek: kod

import pymc
import numpy as np

### Data generation

# Means and standard deviations of the Gaussian mixture model. The inference
# engine doesn't know these.
means = [0, 4.0]
stdevs = [1, 2.0]

# Rather than randomizing between the mixands, just specify how many
# to draw from each. This makes it really easy to know which draws
# came from which mixands (the first N1 from the first, the rest from
# the secon). The inference engine doesn't know about N1 and N2, only Ndata
N1 = 10
N2 = 40
Ndata = N1+N2

# Seed both the data generator RNG  as well as the global seed (for PyMC)
RNGseed = 123
np.random.seed(RNGseed)

def generate_data(draws_per_mixand):
    """Draw samples from a two-element Gaussian mixture reproducibly.

    Input sequence indicates the number of draws from each mixand. Resulting
    draws are concantenated together.

    """
    RNG = np.random.RandomState(RNGseed)
    values = np.hstack([RNG.normal(means[i], stdevs[i], ndraws)
                        for (i,ndraws) in enumerate(draws_per_mixand)])
    return values

observed_data = generate_data([N1, N2])


### PyMC model setup, step 1: the Dirichlet process and stick-breaking

# Truncation level of the Dirichlet process
Ndp = 50

# "alpha", or the concentration of the stick-breaking construction. There exists
# some interplay between choice of Ndp and concentration: a high concentration
# value implies many clusters, in turn implying low values for the leading
# elements of the probability mass function built by stick-breaking. Since we
# enforce the resulting PMF to sum to one, the probability of the last cluster
# might be then be set artificially high. This may interfere with the Dirichlet
# process' clustering ability.
#
# An example: if Ndp===4, and concentration high enough, stick-breaking might
# yield p===[.1, .1, .1, .7], which isn't desireable. You want to initialize
# concentration so that the last element of the PMF is less than or not much
# more than the a few of the previous ones. So you'd want to initialize at a
# smaller concentration to get something more like, say, p===[.35, .3, .25, .1].
#
# A thought: maybe we can avoid this interdependency by, rather than setting the
# final value of the PMF vector, scale the entire PMF vector to sum to 1? FIXME,
# TODO.
concinit = 5.0
conclo = 0.3
conchi = 100.0
concentration = pymc.Uniform('concentration', lower=conclo, upper=conchi,
                             value=concinit)

# The stick-breaking construction: requires Ndp beta draws dependent on the
# concentration, before the probability mass function is actually constructed.
betas = pymc.Beta('betas', alpha=1, beta=concentration, size=Ndp)

@pymc.deterministic
def pmf(betas=betas):
    "Construct a probability mass function for the truncated Dirichlet process"
    # prod = lambda x: np.exp(np.sum(np.log(x))) # Slow but more accurate(?)
    prod = np.prod
    value = map(lambda (i,u): u * prod(1.0 - betas[:i]), enumerate(betas))
    value[-1] = 1.0 - sum(value[:-1]) # force value to sum to 1
    return value

# The cluster assignments: each data point's estimated cluster ID.
# Remove idinit to allow clusterid to be randomly initialized:
idinit = np.zeros(Ndata, dtype=np.int64)
clusterid = pymc.Categorical('clusterid', p=pmf, size=Ndata, value=idinit)

### PyMC model setup, step 2: clusters' means and stdevs

# An individual data sample is drawn from a Gaussian, whose mean and stdev is
# what we're seeking.

# Hyperprior on clusters' means
mu0_mean = 0.0
mu0_std = 50.0
mu0_prec = 1.0/mu0_std**2
mu0_init = np.zeros(Ndp)
clustermean = pymc.Normal('clustermean', mu=mu0_mean, tau=mu0_prec,
                          size=Ndp, value=mu0_init)

# The cluster's stdev
clustersig_lo = 0.0
clustersig_hi = 100.0
clustersig_init = 50*np.ones(Ndp) # Again, don't really care?
clustersig = pymc.Uniform('clustersig', lower=clustersig_lo,
                          upper=clustersig_hi, size=Ndp, value=clustersig_init)
clusterprec = clustersig ** -2

### PyMC model setup, step 3: data

# So now we have means and stdevs for each of the Ndp clusters. We also have a
# probability mass function over all clusters, and a cluster ID indicating which
# cluster a particular data sample belongs to.

@pymc.deterministic
def data_cluster_mean(clusterid=clusterid, clustermean=clustermean):
    "Converts Ndata cluster IDs and Ndp cluster means to Ndata means."
    return clustermean[clusterid]

@pymc.deterministic
def data_cluster_prec(clusterid=clusterid, clusterprec=clusterprec):
    "Converts Ndata cluster IDs and Ndp cluster precs to Ndata precs."
    return clusterprec[clusterid]

data = pymc.Normal('data', mu=data_cluster_mean, tau=data_cluster_prec,
                   observed=True, value=observed_data)

Referanslar

  1. fn1: http://nbviewer.ipython.org/urls/raw.github.com/fonnesbeck/Bios366/master/notebooks/Section5_2-Dirichlet-Processes.ipynb
  2. fn2: http://blog.echen.me/2012/03/20/infinite-mixture-models-with-nonparametric-bayes-and-the-dirichlet-process/
  3. fn3: http://scikit-learn.org/stable/auto_examples/mixture/plot_gmm.html#example-mixture-plot-gmm-py

Bileşen varyansları üzerindeki önceliğiniz, size büyük sorunlara neden olabilecek Düzgün (0,100). Bu önceki kütlenin sadece% 2'si 1 ve 2'nin gerçek varyanslarını kapsar. Bu önceki bileşenlerinizin beklenen varyansı 50'dir; bu, verilerinizi tek bir bileşenle kolayca hesaplayabileceği kadar geniş bir Gauss'tur.
jerad

Hackerlar için Olasılıksal Programlama ve Bayes İstatistikleri kitabının bu bölümünü okudunuz mu? Size yardımcı olabilecek bir örneği var!
Tim

Bu bir cevap için biraz kısa görünüyor. Daha çok bir yorum gibi görünüyor. En azından OP'nin okuyarak hangi bilgileri alacağını anlatabilir misiniz?
Glen_b

@TimRich evet okudum ve lisansüstü okulda dersi aldım ve uygulamalı istatistikler yaparak endüstride çalıştı;) Bu PyMC'ye özgü bir soru.
Ahmed Fasih

1
Önceden hiyerarşik olanı reddetmezdim. Bir karışımın bileşenlerine düz öncelikler koyarsanız, özellikle de aynı anda kümelerin sayısını öğrenmeye çalıştığınızda, kendinizi kötü bir konuma soktuğunuz bilinmektedir . Bence iz alanlarınızdaki tuhaf ani artışlara neden olan şey budur. NP-Bayes büyük adları tüm grubu gibi ve tahmini eklenti ya kullanımı veya yerleştirerek bilgi için tasarlanmış, bu bileşenler üzerinde önceden uygun ölçeklere koyun. μ 0 , σ 0μZiN(μ0,σ0)μ0,σ0
adam

Yanıtlar:


4

Kimse bu soruya artık bakıp bakmadığından emin değilim ama Tom'un Gibbs örnekleme önerisini test etmek için rjag'lere soruyorum ve standart sapmadan önce Guy'dan daire hakkında bilgi ekliyoruz.

Bu oyuncak sorunu zor olabilir, çünkü 10 ve hatta 40 veri noktası, önceden bilgilendirici olmadan varyansı tahmin etmek için yeterli değildir. Geçerli önceki σzi∼Uniform (0,100) bilgilendirici değildir. Bu, μzi'nin neredeyse tüm çizimlerinin neden iki dağılımın beklenen ortalaması olduğunu açıklayabilir. Sorunuzu çok fazla değiştirmezse, sırasıyla 100 ve 400 veri noktası kullanacağım.

Ben de benim kod doğrudan sopa kırma işlemi kullanmıyordu. Wikipedia Dirichlet işlem için bana çağrı p ~ Dir (a / k) Tamam olacağını düşündürdü.

Son olarak, sadece bir dizi parametrik uygulama olduğu için hala birkaç küme almaktadır k. Jaglarda sonsuz bir karışım modelinin nasıl yapılacağını bilmiyorum.

markov zincir mu küme 1

markov zincir mu küme 2

library("rjags")

set1 <- rnorm(100, 0, 1)
set2 <- rnorm(400, 4, 1)
data <- c(set1, set2)

plot(data, type='l', col='blue', lwd=3,
     main='gaussian mixture model data',
     xlab='data sample #', ylab='data value')
points(data, col='blue')

cpd.model.str <- 'model {
  a ~ dunif(0.3, 100)
  for (i in 1:k){
    alpha[i] <- a/k
    mu[i] ~ dnorm(0.0, 0.001)
    sigma[i] ~ dunif(0, 100)
  }
  p[1:k] ~ ddirich(alpha[1:k])
  for (i in 1:n){
    z[i] ~ dcat(p)
    y[i] ~ dnorm(mu[z[i]], pow(sigma[z[i]], -2))
  }
}' 


cpd.model <- jags.model(textConnection(cpd.model.str),
                        data=list(y=data,
                                  n=length(data),
                                  k=5))
update(cpd.model, 1000)
chain <- coda.samples(model = cpd.model, n.iter = 1000,
                      variable.names = c('p', 'mu', 'sigma'))
rchain <- as.matrix(chain)
apply(rchain, 2, mean)

1
Sonlu sayıda kümesi kullanmayla ilgili olarak , sadece alabilir (ve sahip olduğunuz gibi ayarlayabilir ) ve Dirichlet işlemiyle etkili bir şekilde aynı modeli elde edebilirsiniz. Bunun Dirichlet işleminden önce yakınsaması çok hızlıdır; gözlem için gibi bir şey fazlasıyla yeterli olmalıdır. Kullanırken Ayrıca, akıllı üzere, değil çünkü, sopa kıran inşaat kullanmak üzerine blok belirlemez yüklendi ; burada yaptıklarınız daha iyi. K α i = a / K 500 K = 25 pKKαi=a/K500K=25JAGSJAGSp
Adam

1

Gördüğünüz zayıf karıştırma, büyük olasılıkla PyMC'nin örnek çekme yönteminden kaynaklanmaktadır. PyMC belgelerinin 5.8.1 bölümünde açıklandığı gibi , bir dizi değişkeninin tüm elemanları birlikte güncellenir. Sizin durumunuzda, bu, tüm clustermeandiziyi tek bir adımda ve benzer şekilde güncellemeye çalışacağı anlamına gelir clusterid. PyMC Gibbs örneklemesi yapmaz; teklifin basit bir sezgisel tarama tarafından seçildiği Metropolis'i yapar. Bu, tüm dizi için iyi bir değer önermemeyi mümkün kılmaz.


"Bütün diziyi tek bir adımda güncellemeye çalışacaksınız" dediğinde, Metropolis'in (bu örnekte) Gibbs'e karşı dezavantajlarını anladım. STAN veya JAGS hakkında bu konuda daha iyi olmalarına izin verecek özel bir şey var mı? Her iki durumda da, PyMC'de Gibbs'i uygulamak için biraz zaman harcayacağım. Teşekkür ederim! (Işık hızından beri işinizin bir hayranıydım, çok teşekkür ederim!)
Ahmed Fasih

1
STAN ayrık değişkenleri işlemez, ancak JAGS denemeye değer.
Tom Minka
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.