Vấn đề thiết lập
Một trong những vấn đề đồ chơi đầu tiên tôi muốn áp dụng PyMC là phân cụm không theo tỷ lệ: đưa ra một số dữ liệu, mô hình hóa nó như một hỗn hợp Gaussian, và tìm hiểu số lượng cụm và ý nghĩa và hiệp phương sai của từng cụm. Hầu hết những gì tôi biết về phương pháp này đến từ các bài giảng video của Michael Jordan và Yee Whye Teh, vào khoảng năm 2007 (trước khi thưa thớt trở thành cơn thịnh nộ), và vài ngày cuối cùng đọc bài hướng dẫn của Tiến sĩ Fonnesbeck và E. Chen [fn1], [ fn2]. Nhưng vấn đề được nghiên cứu kỹ và có một số triển khai đáng tin cậy [fn3].
Trong bài toán đồ chơi này, tôi tạo ra mười lần rút từ một Gaussian và bốn mươi lần rút từ . Như bạn có thể thấy bên dưới, tôi đã không xáo trộn các bản vẽ, để dễ dàng biết mẫu nào đến từ thành phần hỗn hợp nào.N ( μ = 4 , σ = 2 )
Tôi mô hình hóa từng mẫu dữ liệu , cho và trong đó chỉ ra cụm cho điểm dữ liệu thứ này: . ở đây là độ dài của quá trình Dirichlet bị cắt ngắn được sử dụng: đối với tôi, .i = 1 , . . . , 50 z i i z i ∈ [ 1 , . . . , N D P ] N D P N D P = 50
Mở rộng cơ sở hạ tầng quy trình Dirichlet, mỗi ID cụm được rút ra từ một biến ngẫu nhiên phân loại, có chức năng khối lượng xác suất được đưa ra bởi cấu trúc phá vỡ: với cho a tham số nồng độ . Stick phá cấu trúc các vector -long , mà phải tổng hợp tới 1, bằng cách đầu tiên lấy IID Beta-phân phối thu hút phụ thuộc vào , xem [ct1]. Và vì tôi muốn dữ liệu thông báo cho sự thiếu hiểu biết của mình về , tôi theo dõi [fn1] và giả sử .
Điều này xác định cách tạo ID cụm của mỗi mẫu dữ liệu. Mỗi cụm có độ lệch chuẩn và trung bình liên quan, và . Sau đó, và .
(Trước đây tôi đã sau [ct1] không suy nghĩ và đặt một hyperprior trên , có nghĩa là, với bản thân một trận hòa từ một phân phối bình thường tham số cố định và từ đồng phục. Nhưng theo https://stats.stackexchange.com/a/71932/31187 , dữ liệu của tôi không hỗ trợ loại siêu nhân phân cấp này.)
Tóm lại, mô hình của tôi là:
trong đó chạy từ 1 đến 50 (số lượng mẫu dữ liệu).
và có thể nhận các giá trị trong khoảng từ 0 đến ; , một vectơ dài ; và , vô hướng. (Bây giờ tôi hơi hối hận khi làm cho số lượng mẫu dữ liệu bằng với độ dài bị cắt của Dirichlet trước đó, nhưng tôi hy vọng nó rõ ràng.)
σ z i ~ U n i f o r m ( 0 , 100 ) N D P N D P và . Có về các phương tiện và độ lệch chuẩn này (một cho mỗi cụm có thể.)
Đây là mô hình đồ họa: tên là tên biến, xem phần mã bên dưới.
Báo cáo vấn đề
Mặc dù có một số điều chỉnh và sửa lỗi không thành công, các tham số đã học hoàn toàn không giống với các giá trị thực đã tạo ra dữ liệu.
Hiện tại, tôi đang khởi tạo hầu hết các biến ngẫu nhiên thành các giá trị cố định. Các biến trung bình và độ lệch chuẩn được khởi tạo cho các giá trị dự kiến của chúng (nghĩa là 0 đối với các giá trị bình thường, ở giữa hỗ trợ của chúng cho các giá trị đồng nhất). Tôi khởi tạo tất cả ID cụm thành 0. Và tôi khởi tạo tham số nồng độ . α = 5
Với các khởi tạo như vậy, 100.000 lần lặp MCMC đơn giản là không thể tìm thấy cụm thứ hai. Phần tử đầu tiên của gần bằng 1 và gần như tất cả các lần rút cho tất cả các mẫu dữ liệu đều giống nhau, khoảng 3,5. Tôi hiển thị mỗi lần rút thứ 100 ở đây cho hai mươi mẫu dữ liệu đầu tiên, nghĩa là cho :μ z i i μ z i i = 1 , . . . , 20
Nhắc lại rằng mười mẫu dữ liệu đầu tiên là từ một chế độ và phần còn lại là từ chế độ khác, kết quả trên rõ ràng không thể nắm bắt được điều đó.
Nếu tôi cho phép khởi tạo ngẫu nhiên các ID cụm, thì tôi nhận được nhiều hơn một cụm nhưng cụm có nghĩa là tất cả đi lang thang xung quanh cùng một mức 3,5:
Điều này gợi ý cho tôi rằng đó là vấn đề thường gặp với MCMC, rằng nó không thể đạt đến một chế độ khác của hậu thế từ đó: nhớ lại rằng những kết quả khác nhau này xảy ra sau khi thay đổi khởi tạo ID cụm , không phải là linh mục của chúng hoặc còn gì nữa không.
Tôi có phạm sai lầm nào trong mô hình không? Câu hỏi tương tự: https://stackoverflow.com/q/19114790/500207 muốn sử dụng phân phối Dirichlet và phù hợp với hỗn hợp Gaussian 3 yếu tố và đang gặp vấn đề tương tự. Tôi có nên xem xét việc thiết lập một mô hình liên hợp hoàn toàn và sử dụng lấy mẫu Gibbs cho kiểu phân cụm này không? (Tôi đã triển khai bộ lấy mẫu Gibbs cho trường hợp phân phối Dirichlet tham số, ngoại trừ sử dụng nồng độ cố định , trở lại trong ngày và nó hoạt động tốt, vì vậy mong PyMC có thể giải quyết vấn đề đó ít nhất một cách cẩn thận.)
Phụ lục: mã
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)
Người giới thiệu
- fn1: http://nbviewer.ipython.org/urls/raw.github.com/fonnesbeck/Bios366/master/notebooks/Section5_2-Dirichlet-Processes.ipynb
- fn2: http://blog.echen.me/2012/03/20/infinite-mixture-models-with-nonparametric-bayes-and-the-dirichlet- Process /
- fn3: http://scikit-learn.org/urdy/auto_examples/mixture/plot_gmm.html#example-mixture-plot-gmm-py