HMM Procedure

Gaussian Mixture Hidden Markov Model for Time Series Data and Cross-Sectional Time Series Data

Let bold upper Y Subscript t Baseline equals left-parenthesis y Subscript 1 t Baseline comma ellipsis comma y Subscript p t Baseline right-parenthesis Superscript prime Baseline comma t equals 1 comma ellipsis comma upper T, denote a p-dimensional time series vector of random variables. Conditional on a latent variable bold upper S Subscript t, bold upper Y Subscript t follows a Gaussian mixture distribution,

StartLayout 1st Row  bold upper Y Subscript t Baseline vertical-bar bold upper S Subscript t Baseline tilde normal upper G normal upper M left-parenthesis StartSet w Subscript bold upper S Sub Subscript t Subscript comma 1 Baseline comma ellipsis comma w Subscript bold upper S Sub Subscript t Subscript comma upper M Baseline EndSet comma StartSet mu Subscript bold upper S Sub Subscript t Subscript comma 1 Baseline comma ellipsis comma mu Subscript bold upper S Sub Subscript t Subscript comma upper M Baseline EndSet comma StartSet normal upper Sigma Subscript bold upper S Sub Subscript t Subscript comma 1 Baseline comma ellipsis comma normal upper Sigma Subscript bold upper S Sub Subscript t Subscript comma upper M Baseline EndSet right-parenthesis EndLayout

where the variable bold upper S Subscript t is the (hidden) state; normal upper G normal upper M left-parenthesis period comma period comma period right-parenthesis represents the Gaussian mixture distribution; M is the number of components at each state; and the w Subscript bold upper S Sub Subscript t Subscript comma j Baseline comma j equals 1 comma ellipsis comma upper M, are mixture component probabilities (MCPs, also called mixture weights), which satisfy the basic requirement for weights (w Subscript bold upper S Sub Subscript t Subscript comma j Baseline greater-than-or-equal-to 0 comma j equals 1 comma ellipsis comma upper M comma and sigma-summation Underscript j equals 1 Overscript upper M Endscripts w Subscript bold upper S Sub Subscript t Subscript comma j Baseline equals 1). The mu Subscript bold upper S Sub Subscript t Subscript comma j and normal upper Sigma Subscript bold upper S Sub Subscript t Subscript comma j Baseline comma j equals 1 comma ellipsis comma upper M comma are the mean and covariance parameters for the jth Gaussian component at state bold upper S Subscript t, and their values depend on the variable bold upper S Subscript t. The state variable bold upper S Subscript t follows the first-order Markov chain; that is,

StartLayout 1st Row  p left-parenthesis bold upper S Subscript t Baseline vertical-bar bold upper S Subscript t minus 1 Baseline comma bold upper S Subscript t minus 2 Baseline comma ellipsis comma bold upper S 1 right-parenthesis equals p left-parenthesis bold upper S Subscript t Baseline vertical-bar bold upper S Subscript t minus 1 Baseline right-parenthesis EndLayout

where p left-parenthesis period vertical-bar period right-parenthesis denotes the conditional probability. The range of bold upper S Subscript t is a finite set, StartSet 1 comma ellipsis comma upper K EndSet. The transition probability from state i to state j is expressed as

StartLayout 1st Row  a Subscript i j Baseline equals p left-parenthesis bold upper S Subscript t Baseline equals j vertical-bar bold upper S Subscript t minus 1 Baseline equals i right-parenthesis EndLayout

The upper K times upper K matrix bold upper A equals StartSet a Subscript i j Baseline EndSet is called the transition probability matrix (TPM). The last element in the model is the initial state probability vector (ISPV), pi, of the first state bold upper S 1:

StartLayout 1st Row  pi equals StartSet pi Subscript i Baseline equals p left-parenthesis bold upper S 1 equals i right-parenthesis comma i equals 1 comma ellipsis comma upper K EndSet EndLayout

Because the variable bold upper S Subscript t is unobservable and follows a Markov chain and because bold upper Y Subscript t follows a Gaussian mixture distribution conditional on bold upper S Subscript t, the model is called the Gaussian mixture hidden Markov model (GM HMM). The GM HMM is sometimes described as StartSet pi comma bold upper A comma bold upper B EndSet, where bold upper B identical-to StartSet w Subscript i j Baseline comma mu Subscript i j Baseline comma normal upper Sigma Subscript i j Baseline comma i equals 1 comma ellipsis comma upper K comma j equals 1 comma ellipsis comma upper M EndSet, and it consists of parameters that define the state-dependent distribution of observable variables.

The GM HMM for cross-sectional time series data is similar to the extension from Gaussian HMM to Gaussian HMM for cross-sectional time series data; for more information, see the section Gaussian Hidden Markov Model for Cross-Sectional Time Series Data.

Consider a bistate bi-component GM HMM that has the following parameter values. The ISPV and TPM are

StartLayout 1st Row  pi equals StartBinomialOrMatrix 0.75 Choose 0.25 EndBinomialOrMatrix comma bold upper A equals Start 2 By 2 Matrix 1st Row 1st Column 0.95 2nd Column 0.05 2nd Row 1st Column 0.15 2nd Column 0.85 EndMatrix EndLayout

At state 1, the two components have weights

StartLayout 1st Row  c 11 equals 0.6 comma c 12 equals 0.4 EndLayout

and the mean and covariance parameters for two components are

StartLayout 1st Row  mu 11 equals StartBinomialOrMatrix 1 Choose 1 EndBinomialOrMatrix comma normal upper Sigma 11 equals Start 2 By 2 Matrix 1st Row 1st Column 1 2nd Column 0 2nd Row 1st Column 0 2nd Column 1 EndMatrix comma mu 12 equals StartBinomialOrMatrix negative 3 Choose negative 3 EndBinomialOrMatrix comma normal upper Sigma 12 equals Start 2 By 2 Matrix 1st Row 1st Column 1.69 2nd Column 1.00 2nd Row 1st Column 1.00 2nd Column 1.69 EndMatrix EndLayout

At state 2, the two components have weights

StartLayout 1st Row  c 21 equals 0.7 comma c 22 equals 0.3 EndLayout

and the mean and covariance parameters for two components are

StartLayout 1st Row  mu 21 equals StartBinomialOrMatrix negative 1 Choose negative 1 EndBinomialOrMatrix comma normal upper Sigma 22 equals Start 2 By 2 Matrix 1st Row 1st Column 1 2nd Column 0 2nd Row 1st Column 0 2nd Column 1 EndMatrix comma mu 22 equals StartBinomialOrMatrix 3 Choose 3 EndBinomialOrMatrix comma normal upper Sigma 22 equals Start 2 By 2 Matrix 1st Row 1st Column 1.69 2nd Column 1.00 2nd Row 1st Column 1.00 2nd Column 1.69 EndMatrix EndLayout

The following statements simulate the bivariate vector time series from the previous model to provide test data for the HMM procedure:

%let a11 = 0.98;
%let a22 = 0.95;
%let c1_1 = 0.6;
%let c1_2 = 0.4;
%let c2_1 = 0.7;
%let c2_2 = 0.3;
%let mu1_1_1 = 1;
%let mu1_1_2 = 1;
%let mu1_2_1 = -3;
%let mu1_2_2 = -3;
%let sigma1_1_11 = 1;
%let sigma1_1_21 = 0;
%let sigma1_1_22 = 1;
%let sigma1_2_11 = 1.69;
%let sigma1_2_21 = 1;
%let sigma1_2_22 = 1.69;
%let mu2_1_1 = -1;
%let mu2_1_2 = -1;
%let mu2_2_1 = 3;
%let mu2_2_2 = 3;
%let sigma2_1_11 = 1;
%let sigma2_1_21 = 0;
%let sigma2_1_22 = 1;
%let sigma2_2_11 = 1.69;
%let sigma2_2_21 = 1;
%let sigma2_2_22 = 1.69;
%let seed = 1234;
%let T = 200000;

data gmDGP;
   retain cd1_1_11 cd1_1_21 cd1_1_22
          cd1_2_11 cd1_2_21 cd1_2_22
          cd2_1_11 cd2_1_21 cd2_1_22
          cd2_2_11 cd2_2_21 cd2_2_22;
   do t = 1 to &T.;
      if(t=1) then do;
         * initial probability distribution;
         p = (1-&a22.)/((1-&a11.)+(1-&a22.));;
         * Cholesky decomposition;
         cd1_1_11 = sqrt(&sigma1_1_11.);
         cd1_1_21 = &sigma1_1_21./cd1_1_11;
         cd1_1_22 = sqrt(&sigma1_1_22.-cd1_1_21*cd1_1_21);
         cd1_2_11 = sqrt(&sigma1_2_11.);
         cd1_2_21 = &sigma1_2_21./cd1_2_11;
         cd1_2_22 = sqrt(&sigma1_2_22.-cd1_2_21*cd1_2_21);
         cd2_1_11 = sqrt(&sigma2_1_11.);
         cd2_1_21 = &sigma2_1_21./cd2_1_11;
         cd2_1_22 = sqrt(&sigma2_1_22.-cd2_1_21*cd2_1_21);
         cd2_2_11 = sqrt(&sigma2_2_11.);
         cd2_2_21 = &sigma2_2_21./cd2_2_11;
         cd2_2_22 = sqrt(&sigma2_2_22.-cd2_2_21*cd2_2_21);
      end;
      else do;
         * transition probability matrix;
         if(lags=1) then p = &a11.;
         else p = 1-&a22.;
      end;
      u = uniform(&seed.);
      if(u<=p) then s=1;
      else s = 2;
      e1 = normal(&seed.); e2 = normal(&seed.);
      if(s=1) then do;
         * choose component;
         u = uniform(&seed.);
         if(u<=&c1_1.) then do;
            * (x,y) ~ N(mu, Sigma) at state 1, component 1;
            x = &mu1_1_1. + cd1_1_11*e1;
            y = &mu1_1_2. + cd1_1_21*e1+cd1_1_22*e2;
         end;
         else do;
            * (x,y) ~ N(mu, Sigma) at state 1, component 2;
            x = &mu1_2_1. + cd1_2_11*e1;
            y = &mu1_2_2. + cd1_2_21*e1+cd1_2_22*e2;
         end;
      end;
      else do;
         * choose component;
         u = uniform(&seed.);
         if(u<=&c2_1.) then do;
            * (x,y) ~ N(mu, Sigma) at state 2, component 1;
            x = &mu2_1_1. + cd2_1_11*e1;
            y = &mu2_1_2. + cd2_1_21*e1+cd2_1_22*e2;
         end;
         else do;
            * (x,y) ~ N(mu, Sigma) at state 2, component 2;
            x = &mu2_2_1. + cd2_2_11*e1;
            y = &mu2_2_2. + cd2_2_21*e1+cd2_2_22*e2;
         end;
      end;
      output;
      lags = s;
   end;
run;

data gmTrain;
   set gmDGP(where=(t<=&T./2));
   keep t x y;
run;

data gmTest;
   set gmDGP(where=(t>&T./2));
   keep t x y;
run;

In general, the data generating process is unknown. The data tables gmTrain and gmTest can be seen, but the data table gmDGP cannot be seen.

First, assume that the following statements plot the simulated series x that is contained in the data table gmTrain:

proc sgplot data=gmTrain;
   series x=t y=x;
run;

Figure 22 shows the plot of x, whose points seem to fall randomly around 0.

Figure 22: Plot of Time Series x

Plot of Time Series


The following statements plot the simulated series y that is contained in the data set gmTrain:

proc sgplot data=gmTrain;
   series x=t y=y;
run;

Figure 23 shows the plot of y, whose points also seem to fall randomly around 0.

Figure 23: Plot of Time Series y

Plot of Time Series


Ignoring the sequential information, the following statements plot the observed points left-parenthesis x comma y right-parenthesis that are contained in the data table gmTrain:

proc sgplot data=gmTrain;
   scatter y=y x=x;
run;

Figure 24: Unclassified Observations

Unclassified Observations


As shown in Figure 24, it seems that all points come from one bivariate Gaussian distribution that has a high positive correlation. However, according to the true DGP, some points are from state 1, in which there are two clusters, as shown in Figure 25:

proc sgplot data=gmDGP(where=(t<=&T./2 and s=1));
   scatter y=y x=x;
run;

Figure 25: Observations from State 1

Observations from State 1


Other points are from state 2 in which there are two clusters, as shown in Figure 26:

proc sgplot data=gmDGP(where=(t<=&T./2 and s=2));
   scatter y=y x=x;
run;

Figure 26: Observations from State 2

Observations from State 2


Without considering the sequential order, it is impossible to distinguish the two states.

Before you estimate any model, you should make a copy of the data in the library, as in the following DATA steps:

   data mylib.gmTrain; set gmTrain; run;
   data mylib.gmTest; set gmTest; run;

The following statements estimate the bistate bi-component GM HMM. The type of model is specified in the TYPE= option in the MODEL statement. The number of states is specified in the NSTATE= option in the MODEL statement. The number of components for each state is specified in the NCOMPONENT= option in the MODEL statement. The OUTMODEL= option in the SCORE statement outputs the model information for future scoring on new data table. The LABELSWITCH=(SORT=NONE) option in the PROC HMM statement suppresses the relabeling of states and components; for more information about the label switching problem, see the section Label Switching Problem.

proc hmm data=mylib.gmTrain labelSwitch=(sort=none);
   id time=t;
   model x y / type=gaussianMixture nstate=2 ncomponent=2;
   optimize printLevel=3 printIterFreq=1;
   score outmodel=mylib.gmModel;
run;

These statements assume that your engine libref is named mylib, but you can substitute any appropriately defined engine libref.

The number of observations and model information are shown in Figure 27.

Figure 27: Number of Observations and Model Information

Observation Information
Number of Observations100000
Number of Missing Observations0

Model Information
Type of ModelGaussian Mixture HMM
StationaryYes
Number of States2
Number of Components for a State2
Number of Dependent Variables2


The default method, which is the maximum likelihood method, is applied; this is a nonlinear optimization problem. The initial parameter values and the objective function value at the start of the optimization are shown in Figure 28.

Figure 28: Initial Parameter Values and Objective Function Value

Optimization Start
ParameterEstimate
TPM1_10.500000
TPM1_20.500000
TPM2_10.500000
TPM2_20.500000
MCP1_10.500000
MCP1_20.500000
MCP2_10.500000
MCP2_20.500000
MU1_1_10.416654
MU1_1_20.961871
MU1_2_1-3.422684
MU1_2_2-3.125473
MU2_1_12.963828
MU2_1_21.590644
MU2_2_1-0.815362
MU2_2_2-2.039325
SIGMA1_1_1_11.354409
SIGMA1_1_2_10.762768
SIGMA1_1_2_21.393576
SIGMA1_2_1_10.961355
SIGMA1_2_2_10.661717
SIGMA1_2_2_21.581451
SIGMA2_1_1_11.025889
SIGMA2_1_2_11.399630
SIGMA2_1_2_22.884377
SIGMA2_2_1_10.749535
SIGMA2_2_2_10.265184
SIGMA2_2_2_20.633097

Initial Value of Objective Function-401529.3793


The details of the optimization algorithm are shown in Figure 29.

Figure 29: Optimization Algorithm Details

Algorithm Settings
Maximum Number of Iterations128
Tolerance for Optimality Error1E-6
Tolerance for Infeasibility1E-6
Maximum Allowed Time (seconds)1.797693E308
Maximum Magnitude of Objective Function Value1E20
Random Seed1
Solution Type1
Multi-Start Globalization Scheme0
Multi-Start Globalization Bound Range2


The iterations of the optimization process are shown in Figure 30.

Figure 30: Iterations of the Optimization Process

Iteration History
IterationObjective
Function
Optimality
Error
InfeasibilityFunction
Calls
Gradient
Calls
Hessian
Calls
1-401529.37932887.164660.00000210
2-389554.11582133.361520.000001091
3-386179.65461199.523550.0000019182
4-371985.2011848.191860.0000029283
5-367516.0600249.889330.0000038374
6-366322.8416161.339370.0000049485
7-365982.235246.743620.0000059586
8-365945.51235.297580.0000069687
9-365945.09480.066720.0000079788
10-365945.09460.000000.0000089889


The final parameter values and the objective function value at the end of the optimization are shown in Figure 31.

Figure 31: Final Parameter Values and Objective Function Value

Optimization Results
ParameterEstimate
TPM1_10.979636
TPM1_20.020364
TPM2_10.049729
TPM2_20.950271
MCP1_10.600332
MCP1_20.399668
MCP2_10.297811
MCP2_20.702189
MU1_1_10.993524
MU1_1_20.996707
MU1_2_1-3.003906
MU1_2_2-3.005379
MU2_1_13.005306
MU2_1_23.009691
MU2_2_1-0.997604
MU2_2_2-1.005076
SIGMA1_1_1_11.000305
SIGMA1_1_2_10.007588
SIGMA1_1_2_21.003672
SIGMA1_2_1_11.704270
SIGMA1_2_2_11.003413
SIGMA1_2_2_21.688212
SIGMA2_1_1_11.712932
SIGMA2_1_2_11.014865
SIGMA2_1_2_21.704181
SIGMA2_2_1_11.015895
SIGMA2_2_2_10.012899
SIGMA2_2_2_21.006142

Final Value of Objective Function-365945.0946


The estimates of the initial state probability vector (ISPV) are shown in Figure 32.

Figure 32: Estimates of Initial State Probability Vector

Initial State Probabilities
StateEstimation
10.70947
20.29053


The estimates of the transition probability matrix (TPM) are shown in Figure 33.

Figure 33: Estimates of Transition Probability Matrix

Estimated Transition Probability Matrix
State12
10.979640.02036
20.049730.95027


The estimates of the mixture component probabilities (MCP) are shown in Figure 34.

Figure 34: Estimates of Mixture Component Probabilities

Estimated Mixture Component Probabilities
StateComponent
12
10.600330.39967
20.297810.70219


The estimates of the mean vector of the Gaussian distribution for each component at each state are shown in Figure 35.

Figure 35: Estimate of Mean Vector for Each Component at Each State

Mu
StateComponentxy
110.993520.99671
 2-3.00391-3.00538
213.005313.00969
 2-0.99760-1.00508


The estimates of the covariance matrix of the Gaussian distribution for each component at each state are shown in Figure 36.

Figure 36: Estimate of Covariance Matrix for Each Component at Each State

Sigma
StateComponentVariablexy
11x1.000310.00759
 1y0.007591.00367
 2x1.704271.00341
 2y1.003411.68821
21x1.712931.01486
 1y1.014861.70418
 2x1.015890.01290
 2y0.012901.00614


The estimates of all parameters are shown in Figure 37, which displays columns for the parameter name, estimate value, standard error, t value, and p-value. The state labels ("1" and "2" in this example) and the component labels ("1" and "2" in this example) might exchange randomly, compared to the true DGP. In the preceding estimation, the state labels are the same as the labels in the DGP. The component labels for state 1 are also the same as the ones in the DGP, but the component labels for state 2 do exchange! Compared to the parameter values in the DGP, the estimates are very accurate.

Figure 37: Parameter Estimates

Parameter Estimates
ParameterEstimateStandard
Error
t ValuePr > |t|
TPM1_10.9796360.0006001632.32<.0001
TPM1_20.0203640.00060033.93<.0001
TPM2_10.0497290.00142234.98<.0001
TPM2_20.9502710.001422668.37<.0001
MCP1_10.6003320.001987302.17<.0001
MCP1_20.3996680.001987201.17<.0001
MCP2_10.2978110.002966100.42<.0001
MCP2_20.7021890.002966236.78<.0001
MU1_1_10.9935240.005202191.00<.0001
MU1_1_20.9967070.005225190.77<.0001
MU1_2_1-3.0039060.009259-324.43<.0001
MU1_2_2-3.0053790.009199-326.71<.0001
MU2_1_13.0053060.017586170.89<.0001
MU2_1_23.0096910.017492172.06<.0001
MU2_2_1-0.9976040.007672-130.04<.0001
MU2_2_2-1.0050760.007645-131.47<.0001
SIGMA1_1_1_11.0003050.007559132.33<.0001
SIGMA1_1_2_10.0075880.0056151.350.1765
SIGMA1_1_2_21.0036720.007625131.63<.0001
SIGMA1_2_1_11.7042700.01804094.47<.0001
SIGMA1_2_2_11.0034130.01537265.27<.0001
SIGMA1_2_2_21.6882120.01780894.80<.0001
SIGMA2_1_1_11.7129320.03396050.44<.0001
SIGMA2_1_2_11.0148650.02893935.07<.0001
SIGMA2_1_2_21.7041810.03364850.65<.0001
SIGMA2_2_1_11.0158950.01129589.94<.0001
SIGMA2_2_2_10.0128990.0082891.560.1197
SIGMA2_2_2_21.0061420.01124889.45<.0001


The log likelihood and information criteria are shown in Figure 38.

Figure 38: Log Likelihood and Information Criteria

Fit Statistics
Log Likelihood-365945.0946
AIC731942.18929
AICC731942.20333
BIC732189.52535
HQC732017.24975


The estimates from the data table gmTrain are used to score the testing data table gmTest to check the predictability in the following statements:

proc hmm data=mylib.gmTest;
   score inmodel=mylib.gmModel;
   decode out=mylib.gmDecode;
run;

The accuracy of classification through the GM HMM is calculated by the following statements:

data gmHmmCheck;
   merge gmDGP(in=a where=(t>&T./2)) mylib.gmDecode(in=b);
   by t;
   if(s=state) then do; correct=1; ds = s; end;
   else do; correct=0; ds = -s; end;
   if(a=b);
   keep t x y s correct ds;
run;

%let qFlipState = -1;
data gmHmmAccuracy;
   set gmHmmCheck;
   retain count 0 correctCount 0;
   count = count + 1;
   correctCount = correctCount + correct;
   if(count>&T./2-0.5) then do;
      accuracy = correctCount / count;
      if(accuracy<0.5) then call symputx("qFlipState",1,'G');
      else call symputx("qFlipState",0,'G');
      if(accuracy<0.5) then accuracy = 1 - accuracy;
      output;
   end;
   keep accuracy;
run;

data gmHmmCheck;
   set gmHmmCheck;
   if(&qFlipState.=1) then do;
      ds = -ds;
      correct = 1 - correct;
   end;
run;

proc print data = gmHmmAccuracy noobs; run;

The accuracy of the GM HMM, which is shown in Figure 39, is about 98%. This means that the GM HMM successfully takes advantage of the sequential information.

Figure 39: Accuracy of Decoding by the GM HMM

accuracy
0.97835


Now, consider the GM HMM for cross-sectional time series data. Each section’s data follow the same GM HMM as described previously. The following statements generate the data table for analysis. There are 200 sections in the data table, and each section of time series consist of 1,000 observations.

%let a11 = 0.98;
%let a22 = 0.95;
%let c1_1 = 0.6;
%let c1_2 = 0.4;
%let c2_1 = 0.7;
%let c2_2 = 0.3;
%let mu1_1_1 = 1;
%let mu1_1_2 = 1;
%let mu1_2_1 = -3;
%let mu1_2_2 = -3;
%let sigma1_1_11 = 1;
%let sigma1_1_21 = 0;
%let sigma1_1_22 = 1;
%let sigma1_2_11 = 1.69;
%let sigma1_2_21 = 1;
%let sigma1_2_22 = 1.69;
%let mu2_1_1 = -1;
%let mu2_1_2 = -1;
%let mu2_2_1 = 3;
%let mu2_2_2 = 3;
%let sigma2_1_11 = 1;
%let sigma2_1_21 = 0;
%let sigma2_1_22 = 1;
%let sigma2_2_11 = 1.69;
%let sigma2_2_21 = 1;
%let sigma2_2_22 = 1.69;
%let seed = 1234;
%let T = 200000;
%let nSections = 200;

data gmDGP;
   retain cd1_1_11 cd1_1_21 cd1_1_22
          cd1_2_11 cd1_2_21 cd1_2_22
          cd2_1_11 cd2_1_21 cd2_1_22
          cd2_2_11 cd2_2_21 cd2_2_22;
   do t = 1 to &T.;
      sec = ceil(t*&nSections./&T.);
      if(t=1) then do;
         * initial probability distribution;
         p = (1-&a22.)/((1-&a11.)+(1-&a22.));;
         * Cholesky decomposition;
         cd1_1_11 = sqrt(&sigma1_1_11.);
         cd1_1_21 = &sigma1_1_21./cd1_1_11;
         cd1_1_22 = sqrt(&sigma1_1_22.-cd1_1_21*cd1_1_21);
         cd1_2_11 = sqrt(&sigma1_2_11.);
         cd1_2_21 = &sigma1_2_21./cd1_2_11;
         cd1_2_22 = sqrt(&sigma1_2_22.-cd1_2_21*cd1_2_21);
         cd2_1_11 = sqrt(&sigma2_1_11.);
         cd2_1_21 = &sigma2_1_21./cd2_1_11;
         cd2_1_22 = sqrt(&sigma2_1_22.-cd2_1_21*cd2_1_21);
         cd2_2_11 = sqrt(&sigma2_2_11.);
         cd2_2_21 = &sigma2_2_21./cd2_2_11;
         cd2_2_22 = sqrt(&sigma2_2_22.-cd2_2_21*cd2_2_21);
      end;
      else do;
         * transition probability matrix;
         if(lags=1) then p = &a11.;
         else p = 1-&a22.;
      end;
      u = uniform(&seed.);
      if(u<=p) then s=1;
      else s = 2;
      e1 = normal(&seed.); e2 = normal(&seed.);
      if(s=1) then do;
         * choose component;
         u = uniform(&seed.);
         if(u<=&c1_1.) then do;
            * (x,y) ~ N(mu, Sigma) at state 1, component 1;
            x = &mu1_1_1. + cd1_1_11*e1;
            y = &mu1_1_2. + cd1_1_21*e1+cd1_1_22*e2;
         end;
         else do;
            * (x,y) ~ N(mu, Sigma) at state 1, component 2;
            x = &mu1_2_1. + cd1_2_11*e1;
            y = &mu1_2_2. + cd1_2_21*e1+cd1_2_22*e2;
         end;
      end;
      else do;
         * choose component;
         u = uniform(&seed.);
         if(u<=&c2_1.) then do;
            * (x,y) ~ N(mu, Sigma) at state 2, component 1;
            x = &mu2_1_1. + cd2_1_11*e1;
            y = &mu2_1_2. + cd2_1_21*e1+cd2_1_22*e2;
         end;
         else do;
            * (x,y) ~ N(mu, Sigma) at state 2, component 2;
            x = &mu2_2_1. + cd2_2_11*e1;
            y = &mu2_2_2. + cd2_2_21*e1+cd2_2_22*e2;
         end;
      end;
      output;
      lags = s;
   end;
run;

data gmTrain;
   set gmDGP(where=(sec<=&nSections./2));
   keep sec t x y;
run;

data gmTest;
   set gmDGP(where=(sec>&nSections./2));
   keep sec t x y;
run;

The following statements estimate the GM HMM for the cross-sectional time series data after making the copies of the data tables in the library. The SECTION= option in the ID statement requests that the cross-sectional time series data be analyzed.

data mylib.gmTrain; set gmTrain; run;
data mylib.gmTest; set gmTest; run;

proc hmm data=mylib.gmTrain labelSwitch=(sort=none);
   id time=t section=sec;
   model x y / type=gaussianMixture nstate=2 ncomponent=2;
   optimize printLevel=3 printIterFreq=1;
   score outmodel=mylib.gmModel;
   filter out=mylib.gmFilter;
   evaluate out=mylib.gmEval;
run;

The model information is shown in Figure 40. There are 100 sections in the data.

Figure 40: Model Information

Model Information
Type of ModelGaussian Mixture HMM
StationaryYes
Number of States2
Number of Components for a State2
Number of Dependent Variables2
Number of Sections100


The estimates of all parameters are shown in Figure 41; the estimates are very close to the parameter values in the DGP.

Figure 41: Parameter Estimates

Parameter Estimates
ParameterEstimateStandard
Error
t ValuePr > |t|
TPM1_10.9796970.0005981639.23<.0001
TPM1_20.0203030.00059833.97<.0001
TPM2_10.0499910.00141935.23<.0001
TPM2_20.9500090.001419669.51<.0001
MCP1_10.6003300.001987302.13<.0001
MCP1_20.3996700.001987201.15<.0001
MCP2_10.2978640.002966100.41<.0001
MCP2_20.7021360.002966236.70<.0001
MU1_1_10.9934690.005202190.97<.0001
MU1_1_20.9967500.005224190.80<.0001
MU1_2_1-3.0042800.009259-324.45<.0001
MU1_2_2-3.0057050.009202-326.64<.0001
MU2_1_13.0045170.017596170.75<.0001
MU2_1_23.0089120.017510171.84<.0001
MU2_2_1-0.9974090.007674-129.97<.0001
MU2_2_2-1.0051530.007644-131.50<.0001
SIGMA1_1_1_11.0003320.007560132.32<.0001
SIGMA1_1_2_10.0073210.0056141.300.1922
SIGMA1_1_2_21.0032830.007624131.60<.0001
SIGMA1_2_1_11.7037170.01803494.47<.0001
SIGMA1_2_2_11.0028820.01536865.26<.0001
SIGMA1_2_2_21.6877590.01780694.78<.0001
SIGMA2_1_1_11.7131860.03396950.43<.0001
SIGMA2_1_2_11.0155880.02896435.06<.0001
SIGMA2_1_2_21.7054120.03368950.62<.0001
SIGMA2_2_1_11.0158350.01130189.89<.0001
SIGMA2_2_2_10.0129310.0082911.560.1188
SIGMA2_2_2_21.0058160.01124389.46<.0001


You can apply the estimates from the data table gmTrain to the testing data table gmTest to check the predictability in the following statements:

proc hmm data=mylib.gmTest;
   score inmodel=mylib.gmModel;
   decode out=mylib.gmDecode;
   filter out=mylib.gmFilter2;
   evaluate out=mylib.gmEval2;
run;

data gmHmmCheck;
   merge gmDGP(in=a where=(sec>&nSections./2)) mylib.gmDecode(in=b);
   by t;
   if(s=state) then do; correct=1; ds = s; end;
   else do; correct=0; ds = -s; end;
   if(a=b);
   keep sec t x y s correct ds;
run;

%let qFlipState = -1;
data gmHmmAccuracy;
   set gmHmmCheck;
   retain count 0 correctCount 0;
   count = count + 1;
   correctCount = correctCount + correct;
   if(count>&T./2-0.5) then do;
      accuracy = correctCount / count;
      if(accuracy<0.5) then call symputx("qFlipState",1,'G');
      else call symputx("qFlipState",0,'G');
      if(accuracy<0.5) then accuracy = 1 - accuracy;
      output;
   end;
   keep accuracy;
run;

data gmHmmCheck;
   set gmHmmCheck;
   if(&qFlipState.=1) then do;
      ds = -ds;
      correct = 1 - correct;
   end;
run;

proc print data = gmHmmAccuracy noobs; run;

The accuracy of the GM HMM for cross-sectional time series data, which is shown in Figure 42, is also around 98%.

Figure 42: Accuracy of Decoding by the GM HMM for Cross-Sectional Time Series Data

accuracy
0.97827


Last updated: July 09, 2026