คำตอบนี้จะให้ข้อมูลเชิงลึกเกี่ยวกับสิ่งที่เกิดขึ้นซึ่งนำไปสู่เมทริกซ์ความแปรปรวนร่วมเอกพจน์ในช่วงที่เหมาะสมของ GMM กับชุดข้อมูลสาเหตุที่เกิดขึ้นเช่นเดียวกับสิ่งที่เราสามารถทำได้เพื่อป้องกันไม่ให้
ดังนั้นเราจึงควรเริ่มต้นด้วยการสรุปขั้นตอนในระหว่างการปรับแบบจำลองแบบผสมของเกาส์เซียนเป็นชุดข้อมูล
0. กำหนดจำนวนแหล่งที่มา / กลุ่ม (c) ที่คุณต้องการให้พอดีกับข้อมูลของคุณ
1. เริ่มต้นพารามิเตอร์หมายถึง , ความแปรปรวนร่วมΣ c , และ fraction_per_class π cต่อคลัสเตอร์ c
μcΣcπc
E−Step–––––––––
- คำนวณหาแต่ละดาต้าพอยน์ความน่าจะเป็นr ฉันคดาต้าพอยน์x ฉันเป็นของคลัสเตอร์ c ด้วย:
r i c = π c N ( x i | μ c , Σ c )xiricxi
โดยที่N(x|μ,Σ)อธิบาย mulitvariate Gaussian ด้วย:
N(xi,μc,Σc)=1ric=πcN(xi | μc,Σc)ΣKk=1πkN(xi | μk,Σk)
N(x | μ,Σ)
Rฉันคจะช่วยให้เราแต่ละ DataPointxฉันวัดของ:PRoขขฉันลิตรฉันทีวายทีเอชทีxibelongstoclasN(xi,μc,Σc) = 1(2π)n2|Σc|12exp(−12(xi−μc)TΣ−1c(xi−μc))
ricxiเพราะฉะนั้นถ้าxฉันอยู่ใกล้กับหนึ่งคเกาส์ก็จะได้รับสูงRฉันคค่า สำหรับ Gaussian นี้และมีค่าค่อนข้างต่ำ
M-Step_
สำหรับแต่ละกลุ่ม c: คำนวณน้ำหนักรวมmcProbability that xi belongs to class cProbability of xi over all classesxiric
M−Step––––––––––
mc(พูดหลวม ๆ ส่วนของคะแนนที่จัดสรรให้กับคลัสเตอร์ c) และอัปเดต , μ cและΣ cโดยใช้r i cด้วย:
m c = Σ ฉันr ฉัน c π c = m cπcμcΣcric
mc = Σiric
μc=1πc = mcm
Σc=1μc = 1mcΣiricxi
ว่าคุณต้องใช้วิธีการที่ได้รับการปรับปรุงในสูตรสุดท้ายนี้
ทำซ้ำขั้นตอน E และ M ซ้ำแล้วซ้ำอีกจนกระทั่งฟังก์ชันบันทึกความน่าจะเป็นของโมเดลของเรามาบรรจบกันที่คำนวณความน่าจะเป็นบันทึกด้วย:
lnp(X|π,μ,Σ)=Σ N ฉัน= 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Σ−1c0เมทริกซ์ความแปรปรวนร่วมข้างต้นถ้าหลายตัวแปรแบบเกาส์ตกไปหนึ่งจุดในระหว่างการวนซ้ำระหว่างขั้นตอน E และ M สิ่งนี้อาจเกิดขึ้นได้ถ้าเรามีชุดข้อมูลที่เราต้องการให้พอดีกับ 3 gaussians แต่จริง ๆ แล้วประกอบด้วยสองคลาสเท่านั้น (กลุ่ม) ที่พูดอย่างหลวม ๆ สองสาม gaussians เหล่านี้จับกลุ่มของตัวเองในขณะที่ gussian สุดท้ายเท่านั้นจัดการมัน เพื่อจับจุดเดียวที่มันอยู่ เราจะดูว่าลักษณะนี้เป็นอย่างไรด้านล่าง แต่ทีละขั้นตอน: สมมติว่าคุณมีชุดข้อมูลสองมิติซึ่งประกอบด้วยสองกลุ่ม แต่คุณไม่ทราบว่าและต้องการให้พอดีกับแบบจำลอง gaussian ทั้งสามแบบนั่นคือ c = 3 คุณเริ่มต้นพารามิเตอร์ของคุณในขั้นตอน E และพล็อต gaussians ด้านบนของข้อมูลของคุณซึ่งดู smth เช่น (คุณอาจเห็นกลุ่มกระจัดกระจายสองกลุ่มที่มุมล่างซ้ายและขวาบน):
μcπc
riccovric
ric=πcN(xi | μc,Σc)ΣKk=1πkN(xi | μk,Σk)
ricricxixixiricxiricricΣc = Σiric(xi−μc)T(xi−μc)
ricxi(xi−μc)μcxijμjμj=xnric
[0000]
00มดลูก สิ่งนี้ทำได้โดยการเพิ่มค่าน้อยมาก (ใน
GaussianMixture ของ sklearnค่านี้ถูกตั้งค่าเป็น 1e-6) ไปยัง digonal ของเมทริกซ์ความแปรปรวนร่วม นอกจากนี้ยังมีวิธีอื่นในการป้องกันภาวะเอกฐานเช่นสังเกตเมื่อเกาส์เซียนยุบลงและตั้งค่าเฉลี่ยและ / หรือเมทริกซ์ความแปรปรวนร่วมเป็นค่าสูงใหม่ที่ไม่ได้ตั้งใจ การทำให้เป็นมาตรฐานความแปรปรวนร่วมนี้ยังนำไปใช้ในโค้ดด้านล่างซึ่งคุณจะได้รับผลลัพธ์ที่อธิบายไว้ บางทีคุณต้องรันโค้ดหลาย ๆ ครั้งเพื่อรับเมทริกซ์ความแปรปรวนร่วมเอกพจน์ตั้งแต่นั้นมา สิ่งนี้จะต้องไม่เกิดขึ้นในแต่ละครั้ง แต่ขึ้นอยู่กับการตั้งค่าเริ่มต้นของ 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()