欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

求大神帮我看看这个GMM代码!

程序员文章站 2024-03-22 15:08:34
...

我是MATLAB新手,在论坛上找了一个GMM的代码,但是我放到matlab里面显示“此上下文中不支持函数定义。请在代码文件中创建函数”,请问我需要创建什么样的函数?实在是搞不懂该怎么弄了,求各位大神帮忙看一看!谢谢!!

这是那位大佬的高斯混合模型的代码,我现在有一个1×365的excel数据,我想要得到模型的估计参数值,谢谢大家了!

 

function varargout = gmm(X, K_or_centroids)

% ============================================================

%转载自http://blog.pluskid.org/?p=39

% Expectation-Maximization iteration implementation of

% Gaussian Mixture Model.

%

% PX = GMM(X, K_OR_CENTROIDS)

% [PX MODEL] = GMM(X, K_OR_CENTROIDS)

%

%  - X: N-by-D data matrix.%需要注意的是这里的X包括了全部

%  - K_OR_CENTROIDS: either K indicating the number of

%       components or a K-by-D matrix indicating the

%       choosing of the initial K centroids.

%

%  - PX: N-by-K matrix indicating the probability of each

%       component generating each point.

%  - MODEL: a structure containing the parameters for a GMM:

%       MODEL.Miu: a K-by-D matrix.

%       MODEL.Sigma: a D-by-D-by-K matrix.

%       MODEL.Pi: a 1-by-K vector.

% ============================================================
    threshold = 1e-15;

    [N, D] = size(X);

 

    if
isscalar(K_or_centroids)

        K = K_or_centroids;

        % randomly pick centroids

        rndp = randperm(N);

        centroids = X(rndp(1:K),:);

    else

        K = size(K_or_centroids, 1);

        centroids = K_or_centroids;

    end

 

    % initial values

    [pMiu pPi pSigma] = init_params();

 

    Lprev = -inf;

    while
true

        Px = calc_prob();%计算N(x|mu,sigma)

 

        % new value for pGamma

        pGamma = Px .* repmat(pPi, N, 1);%估计 gamma 是个N*K的矩阵

        pGamma = pGamma ./ repmat(sum(pGamma, 2), 1, K);%对矩阵的理解真是出神入化,

 

        % new value for parameters of each Component

        Nk = sum(pGamma, 1);%N_K

        pMiu = diag(1./Nk) * pGamma' * X; % 数字 *( K-by-N * N-by-D)加个括号有助理解

        pPi = Nk/N;

        for
kk = 1:K

            Xshift = X-repmat(pMiu(kk, : ), N, 1);%x-u

            pSigma(:, :, kk) = (Xshift' * ...

                (diag(pGamma(:, kk)) * Xshift)) / Nk(kk);%更新sigma

        end

 

        % check for convergence

        L = sum(log(Px*pPi'));

        if
L-Lprev < threshold

            break;

        end

        Lprev = L;

    end

 

    if
nargout == 1

        varargout = {Px};

    else

        model = [];

        model.Miu = pMiu;

        model.Sigma = pSigma;

        model.Pi = pPi;

        varargout = {pGamma, model};%注意!!!!!这里和大神代码不同,他返回的是px,而我是 pGamma

    end

 

    function
[pMiu pPi pSigma] = init_params()%初始化参数

        pMiu = centroids;% K-by-D matrix

        pPi = zeros(1, K);%1-by-K matrix

        pSigma = zeros(D, D, K);%

 

        % hard assign x to each centroids

        distmat = repmat(sum(X.*X, 2), 1, K) + ... % X is a N-by-D data matrix.

            repmat(sum(pMiu.*pMiu, 2)', N, 1) - ...% X->K列 U->N行 XU^T is N-by-K

            2*X*pMiu';%计算每个点到K个中心的距离

        [~, labels] = min(distmat, [], 2);%找到离X最近的pMiu,[C,I] labels代表这个最小值是从那列选出来的

 

        for
k=1:K

            Xk = X(labels == k, : );% Xk是所有被归到K类的X向量构成的矩阵

            pPi(k) = size(Xk, 1)/N;% 数一数几个归到K类的

            pSigma(:, :, k) = cov(Xk); %计算协方差矩阵,D-by-D matrix,最小方差无偏估计

        end

    end

 

    function
Px = calc_prob()

        Px = zeros(N, K);

        for
k = 1:K

            Xshift = X-repmat(pMiu(k, : ), N, 1);%x-u

            lemda=1e-5;

            conv=pSigma(:, :, k)+lemda*diag(diag(ones(D)));%这里处理singular问题,为协方差矩阵加上一个很小lemda*I

            inv_pSigma = inv(conv);%协方差的逆

            tmp = sum((Xshift*inv_pSigma) .* Xshift, 2);%(X-U_k)sigma.*(X-U_k),tmp是个N*1的向量

            coef = (2*pi)^(-D/2) * sqrt(det(inv_pSigma));%前面的参数

            Px(:, k) = coef * exp(-0.5*tmp);%把数据点 x 带入到 Gaussian model 里得到的值

        end

    end

end