Jawaban ini akan memberikan wawasan tentang apa yang terjadi yang mengarah ke matriks kovarian singular selama pemasangan GMM ke dataset, mengapa ini terjadi serta apa yang bisa kita lakukan untuk mencegahnya.
Oleh karena itu, sebaiknya kita mulai dengan merekapitulasi langkah-langkah selama pemasangan Model Campuran Gaussian ke dataset.
0. Tentukan berapa banyak sumber / kluster (c) yang Anda inginkan agar sesuai dengan data Anda
1. Inisialisasi parameter berarti μc , covariance , dan fraction_per_classΣc per cluster c
πc
E−Step–––––––––
- Hitung untuk setiap datapoint probabilitas r i c bahwa datapoint x i milik cluster c dengan:
r i c = π c N ( x ixiricxi
di manaN(x|μ,Σ)menjelaskan mulitvariate Gaussian dengan:
N(xi,μc,Σc)=1ric=πcN(xi | μc,Σc)ΣKk=1πkN(xi | μk,Σk)
N(x | μ,Σ)
ricmemberi kita untuk setiap datapointxiukuran:ProbabilitythatxibelongstoclasN(xi,μc,Σc) = 1(2π)n2|Σc|12exp(−12(xi−μc)TΣ−1c(xi−μc))
ricxi maka jikaxisangat dekat dengan salah satu c gaussian, itu akan mendapatkan tinggiricnilai untuk nilai-nilai gaussian dan relatif rendah ini sebaliknya.
M-Step_(longgar berbicara fraksi poin dialokasikan untuk klaster c) dan memperbaruiπcProbability that xi belongs to class cProbability of xi over all classesxiric
M−Step––––––––––
Untuk setiap cluster c: Hitung total berat mcπc , , dan Σ c menggunakan r i c π c = m cμcΣcricdengan:
mc = Σiric
πc = mcm
μc = 1mcΣiricxi
Harap diingat bahwa Anda harus menggunakan cara yang diperbarui dalam formula terakhir ini.
Ulangi langkah E dan M secara berulang sampai fungsi log-likelihood dari model kami bertemu di mana log likelihood dihitung dengan:
lnp(X|π,μ,Σ)=Σ N i = 1 ln(Σ KΣc = 1mcΣiric(xi−μc)T(xi−μc)
ln p(X | π,μ,Σ) = ΣNi=1 ln(ΣKk=1πkN(xi | μk,Σk))
XAX=XA=I
[0000]
AXIΣ−1c0matriks kovarians di atas jika Gaussian Multivarian jatuh ke satu titik selama iterasi antara langkah E dan M. Ini bisa terjadi jika kita memiliki misalnya dataset yang ingin kita masukkan 3 gaussians tetapi yang sebenarnya hanya terdiri dari dua kelas (cluster) sehingga secara longgar, dua dari tiga gaussi ini menangkap cluster mereka sendiri sedangkan gaussian terakhir hanya mengaturnya untuk menangkap satu titik di mana ia duduk. Kita akan melihat bagaimana ini terlihat di bawah. Tetapi langkah demi langkah: Asumsikan Anda memiliki dataset dua dimensi yang terdiri dari dua cluster tetapi Anda tidak tahu itu dan ingin mencocokkan tiga model gaussian, yaitu c = 3. Anda menginisialisasi parameter Anda dalam langkah E dan plot gaussians di atas data Anda yang terlihat suram. seperti (mungkin Anda dapat melihat dua kelompok yang relatif tersebar di kiri bawah dan kanan atas):
μcπc
riccovric
ric=πcN(xi | μc,Σc)ΣKk=1πkN(xi | μk,Σk)
ricricxixixi rsaya cxsaya. (runtuh ke datapoint ini -> Ini terjadi jika semua titik lainnya lebih mungkin bagian dari satu atau dua gaussian dan karenanya ini adalah satu-satunya titik yang tersisa untuk gaussian tiga -> Alasan mengapa hal ini terjadi dapat ditemukan dalam interaksi antara dataset itu sendiri dalam inisialisasi gaussians. Artinya, jika kita telah memilih nilai awal lainnya untuk gaussians, kita akan melihat gambar lain dan gaussian ketiga mungkin tidak akan runtuh). Ini cukup jika Anda semakin jauh paku gaussian ini. Itu
rsaya cmeja kemudian terlihat suram. seperti:
Seperti yang Anda lihat, itu
rsaya cdari kolom ketiga, yaitu untuk gaussian ketiga adalah nol, bukan satu baris ini. Jika kita mencari datapoint mana yang diwakili di sini kita mendapatkan datapoint: [23.38566343 8.07067598]. Ok, tapi mengapa kita mendapatkan matriks singularitas dalam kasus ini? Nah, dan ini adalah langkah terakhir kami, oleh karena itu kami harus sekali lagi mempertimbangkan perhitungan matriks kovarian yaitu:
Σc = Σ sayarsaya c(xsaya-μc)T(xsaya-μc)
kita telah melihat itu semua
rsaya c bukan nol untuk yang satu
xsayadengan [23.38566343 8.07067598]. Sekarang formula ingin kita menghitung
( xsaya- μc). Jika kita melihat
μcuntuk gaussian ketiga ini kita mendapatkan [23.38566343 8.07067598]. Oh, tapi tunggu, itu persis sama dengan
xsaya dan itulah yang ditulis oleh Bishop: "Misalkan salah satu komponen dari model campuran, mari kita katakan
j komponen th, memiliki rerata
μj
persis sama dengan salah satu titik data sehingga
μj= xnuntuk beberapa nilai
n "(Bishop, 2006, p.434). Jadi apa yang akan terjadi? Nah, istilah ini akan menjadi nol dan karenanya datapoint ini adalah satu-satunya kesempatan bagi matriks kovarians untuk tidak mendapatkan nol (karena datapoint ini adalah satu-satunya tempat
rsaya c> 0), sekarang menjadi nol dan terlihat seperti:
[ 0000]
Akibatnya seperti yang disebutkan di atas, ini adalah matriks tunggal dan akan menyebabkan kesalahan selama perhitungan gaussian multivariat. Jadi bagaimana kita bisa mencegah situasi seperti itu. Nah, kita telah melihat bahwa matriks kovarians adalah singular jika itu adalah
0matriks. Karenanya untuk mencegah singularitas kita hanya perlu mencegah agar matriks kovarians menjadi a
0matriks. Hal ini dilakukan dengan menambahkan nilai yang sangat kecil (dalam
GaussianMixture sklearn nilai ini diatur ke 1e-6) ke digonal dari matriks kovarians. Ada juga cara lain untuk mencegah singularitas seperti memperhatikan ketika sebuah gaussian runtuh dan menetapkan mean dan / atau matriks kovariansnya ke nilai baru yang sewenang-wenang. Peraturan kovarian ini juga diterapkan dalam kode di bawah ini yang dengannya Anda mendapatkan hasil yang diuraikan. Mungkin Anda harus menjalankan kode beberapa kali untuk mendapatkan matriks kovarians tunggal, seperti yang dikatakan. ini tidak boleh terjadi setiap kali tetapi juga tergantung pada pengaturan awal gaussians.
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')
from sklearn.datasets.samples_generator import make_blobs
import numpy as np
from scipy.stats import multivariate_normal
# 0. Create dataset
X,Y = make_blobs(cluster_std=2.5,random_state=20,n_samples=500,centers=3)
# Stratch dataset to get ellipsoid data
X = np.dot(X,np.random.RandomState(0).randn(2,2))
class EMM:
def __init__(self,X,number_of_sources,iterations):
self.iterations = iterations
self.number_of_sources = number_of_sources
self.X = X
self.mu = None
self.pi = None
self.cov = None
self.XY = None
# Define a function which runs for i iterations:
def run(self):
self.reg_cov = 1e-6*np.identity(len(self.X[0]))
x,y = np.meshgrid(np.sort(self.X[:,0]),np.sort(self.X[:,1]))
self.XY = np.array([x.flatten(),y.flatten()]).T
# 1. Set the initial mu, covariance and pi values
self.mu = np.random.randint(min(self.X[:,0]),max(self.X[:,0]),size=(self.number_of_sources,len(self.X[0]))) # This is a nxm matrix since we assume n sources (n Gaussians) where each has m dimensions
self.cov = np.zeros((self.number_of_sources,len(X[0]),len(X[0]))) # We need a nxmxm covariance matrix for each source since we have m features --> We create symmetric covariance matrices with ones on the digonal
for dim in range(len(self.cov)):
np.fill_diagonal(self.cov[dim],5)
self.pi = np.ones(self.number_of_sources)/self.number_of_sources # Are "Fractions"
log_likelihoods = [] # In this list we store the log likehoods per iteration and plot them in the end to check if
# if we have converged
# Plot the initial state
fig = plt.figure(figsize=(10,10))
ax0 = fig.add_subplot(111)
ax0.scatter(self.X[:,0],self.X[:,1])
for m,c in zip(self.mu,self.cov):
c += self.reg_cov
multi_normal = multivariate_normal(mean=m,cov=c)
ax0.contour(np.sort(self.X[:,0]),np.sort(self.X[:,1]),multi_normal.pdf(self.XY).reshape(len(self.X),len(self.X)),colors='black',alpha=0.3)
ax0.scatter(m[0],m[1],c='grey',zorder=10,s=100)
mu = []
cov = []
R = []
for i in range(self.iterations):
mu.append(self.mu)
cov.append(self.cov)
# E Step
r_ic = np.zeros((len(self.X),len(self.cov)))
for m,co,p,r in zip(self.mu,self.cov,self.pi,range(len(r_ic[0]))):
co+=self.reg_cov
mn = multivariate_normal(mean=m,cov=co)
r_ic[:,r] = p*mn.pdf(self.X)/np.sum([pi_c*multivariate_normal(mean=mu_c,cov=cov_c).pdf(X) for pi_c,mu_c,cov_c in zip(self.pi,self.mu,self.cov+self.reg_cov)],axis=0)
R.append(r_ic)
# M Step
# Calculate the new mean vector and new covariance matrices, based on the probable membership of the single x_i to classes c --> r_ic
self.mu = []
self.cov = []
self.pi = []
log_likelihood = []
for c in range(len(r_ic[0])):
m_c = np.sum(r_ic[:,c],axis=0)
mu_c = (1/m_c)*np.sum(self.X*r_ic[:,c].reshape(len(self.X),1),axis=0)
self.mu.append(mu_c)
# Calculate the covariance matrix per source based on the new mean
self.cov.append(((1/m_c)*np.dot((np.array(r_ic[:,c]).reshape(len(self.X),1)*(self.X-mu_c)).T,(self.X-mu_c)))+self.reg_cov)
# Calculate pi_new which is the "fraction of points" respectively the fraction of the probability assigned to each source
self.pi.append(m_c/np.sum(r_ic))
# Log likelihood
log_likelihoods.append(np.log(np.sum([k*multivariate_normal(self.mu[i],self.cov[j]).pdf(X) for k,i,j in zip(self.pi,range(len(self.mu)),range(len(self.cov)))])))
fig2 = plt.figure(figsize=(10,10))
ax1 = fig2.add_subplot(111)
ax1.plot(range(0,self.iterations,1),log_likelihoods)
#plt.show()
print(mu[-1])
print(cov[-1])
for r in np.array(R[-1]):
print(r)
print(X)
def predict(self):
# PLot the point onto the fittet gaussians
fig3 = plt.figure(figsize=(10,10))
ax2 = fig3.add_subplot(111)
ax2.scatter(self.X[:,0],self.X[:,1])
for m,c in zip(self.mu,self.cov):
multi_normal = multivariate_normal(mean=m,cov=c)
ax2.contour(np.sort(self.X[:,0]),np.sort(self.X[:,1]),multi_normal.pdf(self.XY).reshape(len(self.X),len(self.X)),colors='black',alpha=0.3)
EMM = EMM(X,3,100)
EMM.run()
EMM.predict()