高斯混合模型参数估计 使用EM算法对一维或者高维的高斯混合模型GMM进行密度函数参数估计
高斯混合模型参数估计 使用EM算法对一维或者高维的高斯混合模型GMM进行密度函数参数估计算法使用kmeans参数初始化使用EM算法进行迭代求解 算法为Matlab编写逻辑清晰注释全面直接上干货。咱们今天聊聊怎么用Matlab实现高斯混合模型GMM的参数估计重点是用EM算法迭代求解。整个过程从kmeans初始化开始手把手教你从零搭建一个能跑通的GMM模型。先看参数初始化部分。这里用kmeans确定初始聚类中心简单粗暴但有效function [mu, sigma, alpha] init_params(data, K) [idx, centers] kmeans(data, K); % K个聚类中心 mu centers; % 转置为列向量 sigma zeros(1, 1, K); alpha zeros(K, 1); for k 1:K cluster_data data(idx k); sigma(:,:,k) var(cluster_data); % 每个簇的方差 alpha(k) sum(idx k)/length(data); % 混合系数 end end这段代码有意思的地方在于sigma的计算。注意三维数组的维度处理——虽然是一维数据但保持高维扩展性。混合系数alpha直接按样本比例分配这比随机初始化靠谱多了。接下来是EM算法的核心循环。先看E步计算后验概率function gamma e_step(x, mu, sigma, alpha) K length(alpha); N length(x); prob zeros(N, K); for k 1:K prob(:,k) alpha(k) * normpdf(x, mu(k), sqrt(sigma(:,:,k))); end gamma prob ./ sum(prob, 2); % 按行归一化 end这里的gamma矩阵就是传说中的责任值。注意normpdf的参数处理——sigma需要开平方很多新手会在这里踩坑。sum(prob,2)这个操作让每行的概率和为1确保后验概率的合法性。高斯混合模型参数估计 使用EM算法对一维或者高维的高斯混合模型GMM进行密度函数参数估计算法使用kmeans参数初始化使用EM算法进行迭代求解 算法为Matlab编写逻辑清晰注释全面M步的参数更新才是重头戏function [mu_new, sigma_new, alpha_new] m_step(x, gamma) [N, K] size(gamma); mu_new sum(gamma.*x) ./ sum(gamma); % 加权平均 sigma_new zeros(1,1,K); for k 1:K diff x - mu_new(k); sigma_new(:,:,k) (gamma(:,k) * (diff.^2)) / sum(gamma(:,k)); end alpha_new mean(gamma); % 直接取平均 endmu的计算用了点乘技巧比循环高效。sigma更新时注意保持维度一致性——这里故意用三维数组方便后续扩展到多维情况。alpha更新简单到令人发指就是各分量的平均责任值。主函数把这几部分串起来function [mu, sigma, alpha, log_likelihood] gmm_em(x, K, max_iter, tol) % 初始化 [mu, sigma, alpha] init_params(x, K); prev_loglik -inf; for iter 1:max_iter % E步 gamma e_step(x, mu, sigma, alpha); % M步 [mu, sigma, alpha] m_step(x, gamma); % 计算似然值 log_likelihood sum(log(sum(alpha .* normpdf(x, mu, sqrt(sigma)), 2))); % 收敛判断 if abs(log_likelihood - prev_loglik) tol break; end prev_loglik log_likelihood; end end这里有个小技巧对数似然的计算避免了下溢问题。注意normpdf的参数排列方式mu需要转置才能正确广播。收敛条件设为对数似然变化小于阈值通常取1e-6左右就够用了。实际跑代码时要注意几个坑方差可能坍缩到0——加个极小值做正则化K值选太大容易过拟合——用BIC准则选择初始值影响大——可以多次随机初始化取最优代码里故意保留了一些不完美的设计比如直接用kmeans结果而没做多次尝试这是为了保持代码的简洁性。实际工程中可能需要加入防止空簇的机制比如当某个簇的样本数为零时重新初始化。最后说个冷知识Matlab自带的gmdistribution.fit其实就是用EM实现的但自己撸代码的好处是可以随意魔改。比如想加个正则项防止过拟合或者改收敛条件自己写的代码就灵活多了。