% Softmax regression for multi-class classification (SRMCC).
% The minimization is carried out by ML-BFGS.
% Inputs:
% Dtr: (N+1) x P train data matrix of K classes of samples. 
%      Its last row are class labels between 1 and K.
% fname: regularized softmax cost function defined by Eq. (3.6).
% gname: gradient of the cost function given by Eqs.(3.8a) and (3.8b).
% mu: regularization parameter \mu.
% K: number of classes in the data sets.
% iter: number of iterations to be performed.
% Outputs:
% Ws: optimized weight-and-bias matrix of size (N+1) by K.
% C: confusion matrix.
% rtm: misclassification rate.
% Prepared by W.-S. Lu, University of Victoria.
% Last modofied: Dec. 5, 2021.
% Example 1: 
% load D_iris
% [Ws,C] = srmc_cg(D_iris,D_iris,0,3,8);
% Example 2:
% load X1600; load Lte28; load Te28;
% [Dtr,Dte,Dhtr,Dhte] = prep_srmc(X1600,Te28,Lte28,7,7);
% Case 1:
% [Ws1,C1] = srmc_cg(Dtr,Dte,0,10,778);
% Case 2 (HOG):
% [Ws2,C2] = srmc_cg(Dhtr,Dhte,0,10,1734);
function [Ws,C] = srmc_cg(Dtr,Dte,mu,K,iter)
N1 = size(Dtr,1);
muK = [mu K];
W0 = zeros(N1,K);
k = 0;
xk = W0(:);
gk = g_srmc(xk,Dtr,muK);
dk = -gk;
ac = 0;
while k < iter
    ak = bt_lsearch2021(xk,dk,gk,'f_srmc',Dtr,muK);
    xk_new = xk + ak*dk;  
    gk_new = g_srmc(xk_new,Dtr,muK);
    gmk = gk_new - gk;
    bk = max((gk_new'*gmk)/(gk'*gk),0);
    dk = -gk_new + bk*dk;
    xk = xk_new;
    gk = gk_new;
    k = k + 1;
end
Ws = reshape(xk_new,N1,K);
    C = zeros(K,K);
    [N1,T] = size(Dte);
    ytest = Dte(N1,:);
    Dtest = [Dte(1:N1-1,:);ones(1,T)];
    te = Dtest'*Ws; 
    [~,ind_pre] = max(te');
    for j = 1:K
        ind_j = find(ytest == j);
        for i = 1:K
            ind_pre_i = find(ind_pre == i);
            C(i,j) = length(intersect(ind_j,ind_pre_i));
        end
    end
disp('confusion matrix:')
C
disp('miscallsification rate:')
rtm = (1 - trace(C)/sum(sum(C)))*100
disp('accuracy:')
100 - rtm