在之前的篇章中,我们介绍了高斯混合模型(GMM)及其基本实现。本文将扩展这一模型,重点是引入早停机制来提高训练效率,并且在训练过程中每隔一定的迭代次数绘制聚类结果,以便观察模型的收敛情况。

引入早停机制

        为了避免不必要的计算,我们可以在训练过程中引入早停机制。具体来说,当对数似然(Log-Likelihood)在迭代过程中不再显著改善时,我们将停止迭代。由于对数似然值在概率模型中通常为负数,优化时我们期望这个值变得更小,但要注意不要忽略负号。

代码实现

        下面是修改后的 GMM 代码示例,它实现了早停机制并在每5次迭代后绘制当前的聚类结果:

from scipy.stats import multivariate_normal
import math
from sklearn.datasets import make_blobs
import numpy as np
import matplotlib.pyplot as plt

# 生成数据
X, y = make_blobs(n_samples=1500, cluster_std=[1.0, 3.5, 0.5], random_state=42)

# 初始化参数
m, n = X.shape
K = 3
max_iter = 20
tol = 1e-4
oldNLL = -np.inf

# 初始化责任矩阵、混合系数、均值和协方差矩阵
r = np.full(shape=(m, K), fill_value=1/K)
pi = np.full((K,), fill_value=1/K)
random_row = np.random.randint(low=0, high=m, size=K)
mean = np.array([X[idx, :] for idx in random_row]).T
cov = np.array([np.cov(X.T) for _ in range(K)])

for iteration in range(max_iter):
    # E步:更新每个样本的责任矩阵
    for i in range(m):
        for k in range(K):
            xi_pdf = multivariate_normal.pdf(X[i], mean=mean[:, k], cov=cov[k])
            r[i, k] = pi[k] * xi_pdf
        r[i] /= np.sum(r[i])

    # 计算对数似然
    NLL = 0
    for i in range(m):
        for k in range(K):
            NLL += math.log(pi[k])
            NLL += multivariate_normal.logpdf(X[i], mean=mean[:, k], cov=cov[k])

    # 检查对数似然是否改进
    if np.abs(NLL - oldNLL) < tol:
        print(f"Converged at iteration {iteration}")
        break
    oldNLL = NLL

    # 每5次迭代绘制一次聚类结果
    if iteration % 5 == 0:
        preds = np.argmax(r, axis=1)
        plt.figure(figsize=(8, 6))
        plt.scatter(X[:, 0], X[:, 1], c=preds, cmap='viridis', s=30)
        plt.title(f'GMM Clustering at Iteration {iteration}')
        plt.show()

如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!

欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

谢谢大家的支持!

09-03 07:33