SMC Procedure

Example 27.4 Estimating the Dynamic Bayesian Network

This example illustrates how to estimate a dynamic Bayesian network (DBN). A heating, ventilation, and air conditioning (HVAC) system is used as a prototype network of DBN.

In this HVAC system, there are four state variables:

  • OutSensorStatus: category variable, outer sensor status (WORK=1 or FAIL=0)

  • InSensorStatus: category variable, inner sensor status (WORK=1 or FAIL=0)

  • OutTemp: continuous variable, actual outer temperature

  • InTemp: continuous variable, actual inner temperature

There are three observation variables:

  • OutTempRead: dependent continuous variable, outer temperature reading

  • InTempRead: dependent continuous variable, inner temperature reading

  • HVAC: independent category variable, HVAC mode (heating, cooling or normal)

The HVAC system can be represented by the following state space model (or the DBN model), where the subscript t denotes the time index:

  • Initialization distributions:

    StartLayout 1st Row 1st Column Blank 2nd Column OutSensorStatus Subscript 1 Baseline tilde Bernoulli left-parenthesis 0.5 right-parenthesis 2nd Row 1st Column Blank 2nd Column InSensorStatus Subscript 1 Baseline tilde Bernoulli left-parenthesis 0.5 right-parenthesis 3rd Row 1st Column Blank 2nd Column OutTemp Subscript 1 Baseline tilde upper N left-parenthesis OutTempRead Subscript 1 Baseline comma 4 right-parenthesis 4th Row 1st Column Blank 2nd Column InTemp Subscript 1 Baseline tilde upper N left-parenthesis InTempRead Subscript 1 Baseline comma 4 right-parenthesis EndLayout
  • Transition distributions:

    StartLayout 1st Row 1st Column Blank 2nd Column normal upper P normal r left-parenthesis OutSensorStatus Subscript t Baseline equals j vertical-bar OutSensorStatus Subscript t minus 1 Baseline equals i right-parenthesis equals upper P Subscript i j Baseline comma i comma j element-of StartSet 0 comma 1 EndSet 2nd Row 1st Column Blank 2nd Column normal upper P normal r left-parenthesis InSensorStatus Subscript t Baseline equals j vertical-bar InSensorStatus Subscript t minus 1 Baseline equals i right-parenthesis equals upper Q Subscript i j Baseline comma i comma j element-of StartSet 0 comma 1 EndSet 3rd Row 1st Column Blank 2nd Column OutTemp Subscript t Baseline equals OutTemp Subscript t minus 1 Baseline plus StartFraction 45 pi Over 287 EndFraction cosine left-parenthesis StartFraction 2 pi Over 287 EndFraction left-parenthesis t minus 2 right-parenthesis minus StartFraction pi Over 2 EndFraction right-parenthesis plus epsilon Subscript t Baseline comma epsilon Subscript t Baseline tilde upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript OT Baseline right-parenthesis 4th Row 1st Column Blank 2nd Column InTemp Subscript t Baseline equals a Subscript i Baseline InTemp Subscript t minus 1 Baseline plus b Subscript i Baseline OutTemp Subscript t minus 1 Baseline plus eta Subscript i comma t Baseline comma eta Subscript i comma t Baseline tilde upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript i comma IT Baseline right-parenthesis comma i equals HVAC Subscript t minus 1 Baseline EndLayout
  • Measurement distributions:

    StartLayout 1st Row 1st Column OutTempRead Subscript t 2nd Column equals StartLayout Enlarged left-brace 1st Row 1st Column Blank 2nd Column OutTemp Subscript t Baseline plus xi Subscript 2 comma t Baseline comma xi Subscript 2 comma t Baseline tilde Overscript iid Endscripts upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript 1 Baseline right-parenthesis comma if OutSensorStatus Subscript t Baseline equals 1 2nd Row 1st Column Blank 2nd Column OutTempRead Subscript t minus 1 Baseline plus xi Subscript 1 comma t Baseline comma xi Subscript 1 comma t Baseline tilde Overscript iid Endscripts upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript 0 Baseline right-parenthesis comma if otherwise EndLayout 2nd Row 1st Column InTempRead Subscript t 2nd Column equals StartLayout Enlarged left-brace 1st Row 1st Column Blank 2nd Column InTemp Subscript t Baseline plus xi Subscript 2 comma t Baseline comma xi Subscript 2 comma t Baseline tilde Overscript iid Endscripts upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript 1 Baseline right-parenthesis comma if InSensorStatus Subscript t Baseline equals 1 2nd Row 1st Column Blank 2nd Column InTempRead Subscript t minus 1 Baseline plus xi Subscript 1 comma t Baseline comma xi Subscript 1 comma t Baseline tilde Overscript iid Endscripts upper N left-parenthesis 0 comma normal upper V normal a normal r Subscript 0 Baseline right-parenthesis comma otherwise EndLayout EndLayout

Here Bernoulli left-parenthesis p right-parenthesis denotes the Bernoulli distribution whose probability of success is p (success: 1; failure: 0), and upper N left-parenthesis mu comma sigma squared right-parenthesis denotes the normal distribution, whose mean is mu and variance is sigma squared. Figure 34 shows the relationships within the HVAC system.

Figure 34: DBN States and Their Transitions

DBN States and Their Transitions


There are 16 parameters. The initial values, bounds, and actual values that the simulation data set uses for the parameters are listed in Table 23. Each of the variance parameters technically has an upper bound of normal infinity, but they are constrained to have an upper bound of 0.99. This represents prior information that the variances cannot be larger than 0.99, which makes sense for this example because it is known that the true values of these parameters are all less than 0.99. Also, adding these constraints makes the model significantly easier to fit.

Table 23: Parameter Information

Parameter Initial Value Range Actual Value
theta 1 equals upper P Subscript 0 comma 0 0.65 (0.01, 0.99) 0.85
theta 2 equals upper P Subscript 1 comma 0 0.3 (0.01, 0.99)0.15
theta 3 equals upper Q Subscript 0 comma 0 0.65 (0.01, 0.99) 0.85
theta 4 equals upper Q Subscript 1 comma 0 0.3 (0.01, 0.99) 0.15
theta 5 equals a 1 0.65 (0.01, 0.99)0.9
theta 6 equals b 1 0.3 (0.01, 0.99)0.2
theta 7 equals normal upper V normal a normal r Subscript 1 comma IT 0.7(0.01, 0.99)0.85
theta 8 equals a 1 0.55 (0.01, 0.99) 0.7
theta 9 equals b 1 0.3 (0.01, 0.99) 0.2
theta 10 equals normal upper V normal a normal r Subscript 2 comma IT 0.7 (0.01, 0.99) 0.85
theta 11 equals a 10.6 (0.01, 0.99)0.8
theta 12 equals b 10.3 (0.01, 0.99) 0.2
theta 13 equals normal upper V normal a normal r Subscript 3 comma IT 0.7 (0.01, 0.99) 0.85
theta 14 equals normal upper V normal a normal r Subscript OT 0.6(0.01, 0.99)0.3
theta 15 equals normal upper V normal a normal r Subscript 1 0.6(0.01, 0.99)0.4
theta 16 equals normal upper V normal a normal r Subscript 0 0.5 (0.01, 0.99) 0.2


The following statements simulate 288 observations on the basis of the given HVAC system:


data hvacSystem;
   call streaminit(123);
   OSlag = 0;
   ISlag = 0;
   OTlag = 55;
   ITlag = 70;
   OTReadlag = 58;
   ITReadlag = 67;
   HVAClag = 3;
   pi=constant("pi");
   do t = 1 to 288*2;
      time = t;
      u = rand("uniform");
      if OSlag = 0 then OS=ifn(u<0.85,0,1);
      else OS=ifn(u<0.15,0,1);
      u = rand("uniform");
      if ISlag = 0 then IS=ifn(u<0.85,0,1);
      else IS=ifn(u<0.15,0,1);
      OT = OTlag+45*pi/287*cos(2*pi/287*(t-2)-0.5*pi)+ sqrt(0.3)*rand("normal");
      if HVAClag = 1 then IT = 0.9*ITlag + 0.2*OTlag + sqrt(0.85)*rand("normal");
      if HVAClag = 2 then IT = 0.7*ITlag + 0.2*OTlag + sqrt(0.85)*rand("normal");
      if HVAClag = 3 then IT = 0.8*ITlag + 0.2*OTlag + sqrt(0.85)*rand("normal");
      if OS = 0 then OTRead = OTReadlag + sqrt(0.4)*rand("normal");
      else OTRead = OT + sqrt(0.2)*rand("normal");
      if IS = 0 then ITRead = ITReadlag + sqrt(0.4)*rand("normal");
      else ITRead = IT + sqrt(0.2)*rand("normal");
      if IT < 68 then HVAC = 1;
      else HVAC=ifn(IT>74,2,3);
      output;
      OTReadlag = OTRead;
      ITReadlag = ITRead;
      OSlag = OS;
      ISlag = IS;
      OTlag = OT;
      ITlag = IT;
      HVAClag = HVAC;
   end;
run;

The following DATA step loads the data set hvacSystem into a data table in your session that is associated with the mylib libref. The DATA step assumes that your libref is named mylib, but you can substitute any appropriately defined libref.

data mylib.hvacSystem;
   set hvacSystem;
run;

In the SMC procedure, two categorical variables must be positioned before the two noncategorical ones in the state variable vector left-brace x Subscript i Baseline right-brace Subscript i equals 1 Superscript 4. For the four state variables, x 1 denotes OutSensorStatus; x 2 denotes InSensorStatus; x 3 denotes OutTemp; and x 4 denotes InTemp.

For the two dependent variables, OutTempRead is denoted by y 1 and InTempRead is denoted by y 2. The independent variable, HVAC, is denoted by z 1.

The following statements use the SUBMITMODEL statement in the SMC procedure to define the HVAC system and then use the PMCMC method to estimate the 16 parameters for the simulated data set. The median of the posterior parameter samples will be used as the parameter in the smoothing process. Moreover, in the SUBMITMODEL statement, theta Subscript i is represented as theta left-bracket i right-bracket for i equals 1 comma ellipsis comma 16; x Subscript i is represented by x left-bracket i right-bracket for i equals 1 comma ellipsis comma 4; y Subscript i is represented by y left-bracket i right-bracket for i equals 1 comma 2; and z 1 is represented by z left-bracket 1 right-bracket. You must specify the dependent-variables in the SUBMITMODEL statement in the same order as left-brace y Subscript i Baseline right-brace Subscript i equals 1 Superscript 2. This example can take around 14 hours or longer to run, depending on which hardware you run it on. The TRANSFORM option for the PMCMC method in the LEARN statement significantly improves the efficiency of the sampler for this model, especially when you combine it with the constraints on the variance parameters.

proc smc data=mylib.hvacSystem  nthreads=32 seed=1;
   id time = t;
   learn nparticle=8000 algorithm=BF method=PMCMC(nsample=40000
        samsum samset nbi=20000 thin=5 seed=123
        outpost = mylib.outle sampler = rwm(transform ntu=700 ntunestage=48)
        statistics = all diagnostics(settings)=all) ;
   smooth nparticle = 20480 alg=bf parm=median method=fixedlag(30) out=mylib.sm;
   submitmodel OTRead ITRead = HVAC / nstate(2,2)=4 nParm = 16 name=dbn
      xlag = (state=1) ylag=(model=1) zlag=(state=1);
      subroutine dbn_sampprio(theta[*]);
         outargs theta;
         theta[1] = 0.65;
         theta[2] = 0.3;
         theta[3] = 0.65;
         theta[4] = 0.3;
         theta[5] = 0.65;
         theta[6] = 0.3;
         theta[7] = 0.7;
         theta[8] = 0.55;
         theta[9] = 0.3;
         theta[10] = 0.7;
         theta[11] = 0.6;
         theta[12] = 0.3;
         theta[13] = 0.7;
         theta[14] = 0.6;
         theta[15] = 0.6;
         theta[16] = 0.5;
      endsub;

      subroutine dbn_lowerbounds(theta[*]);
         outargs theta;
         theta[1] = 0.01;
         theta[2] = 0.01;
         theta[3] = 0.01;
         theta[4] = 0.01;
         theta[5] = 0.01;
         theta[6] = 0.01;
         theta[7] = 0.01;
         theta[8] = 0.01;
         theta[9] = 0.01;
         theta[10] = 0.01;
         theta[11] = 0.01;
         theta[12] = 0.01;
         theta[13] = 0.01;
         theta[14] = 0.01;
         theta[15] = 0.01;
         theta[16] = 0.01;
      endsub;

      subroutine dbn_upperbounds(theta[*]);
         outargs theta;
         theta[1] = 0.99;
         theta[2] = 0.99;
         theta[3] = 0.99;
         theta[4] = 0.99;
         theta[5] = 0.99;
         theta[6] = 0.99;
         theta[8] = 0.99;
         theta[9] = 0.99;
         theta[11] = 0.99;
         theta[12] = 0.99;

         theta[7] = 0.99;
         theta[10] = 0.99;
         theta[13] = 0.99;
         theta[14] = 0.99;
         theta[15] = 0.99;
         theta[16] = 0.99;
      endsub;

      subroutine dbn_sampinit(x[*],xlag[*],ylag[*],z[*],zlag[*],theta[*],_time);
         outargs x, xlag;
         a = rand('uniform');
         x[1] = ifn(a<0.5, 1, 0); /*OutStatus*/
         a = rand('uniform');
         x[2] = ifn(a<0.5, 1, 0); /*InnerStatus*/
         x[3] = 57 + 2*rand('NORMAL', 0, 1); /*OutTempRead*/
         x[4] = 66 + 2*rand('NORMAL', 0, 1); /*InTempRead*/
      endsub;

      function dbn_evalmeas(x[*],xlag[*],y[*],ylag[*],z[*],zlag[*],theta[*],_time);
         if x[1] = 0 then lp1 = LOGPDF('NORMAL',y[1],ylag[1],sqrt(theta[15]));
         else lp1 = LOGPDF('NORMAL',y[1],x[3],sqrt(theta[16]));
         if x[2] = 0 then lp2 = LOGPDF('NORMAL',y[2],ylag[2],sqrt(theta[15]));
         else lp2 = LOGPDF('NORMAL',y[2],x[4],sqrt(theta[16]));
         return (lp1+lp2);
      endsub;

      subroutine dbn_samptran(x[*],xlag[*],ylag[*],z[*],zlag[*],theta[*],_time);
         outargs x;
         pi=constant('PI');
         a = rand('uniform');
         if xlag[1] = 0 then x[1] = ifn(a<theta[1],0,1);
         if xlag[1] = 1 then x[1] = ifn(a<theta[2],0,1);
         a = rand('uniform');
         if xlag[2] = 0 then x[2] = ifn(a<theta[3],0,1);
         if xlag[2] = 1 then x[2] = ifn(a<theta[4],0,1);
         x[3] = xlag[3] + 45*pi/287*cos(2*pi/287*(_time-2)-0.5*pi)
            +sqrt(theta[14])*rand('NORMAL', 0, 1);
         if zlag[1] = 1 then x[4] = theta[5]*xlag[4] + theta[6]*xlag[3]
            +sqrt(theta[7])*rand('NORMAL', 0, 1);
         if zlag[1] = 2 then x[4] = theta[8]*xlag[4] + theta[9]*xlag[3]
            + sqrt(theta[10])*rand('NORMAL', 0, 1);
         if zlag[1] = 3 then x[4] = theta[11]*xlag[4] + theta[12]*xlag[3]
            +sqrt(theta[13])*rand('NORMAL', 0, 1);
      endsub;

      function dbn_evalprio(theta[*]);
         return (0);
      endsub;
   endsubmit;
run;

The summary tables of the model information are shown in Figure 35.

Figure 35: Model Information Summary

Model Information Summary


The summary tables of the posterior samples are shown in Figure 36.

Figure 36: Posterior Summary

Posterior Summary


The correlation and covariance matrices of the parameter samples that the PMCMC method generates are shown in Figure 37.

Figure 37: Correlation and Covariance Matrices

Correlation and Covariance Matrices


The following statements load the smoothing estimates for each state variable into the Work library and then sort each data set by the time ID:

data smo_s1; set mylib.sm(where=(variableID=1)); run;
proc sort data=smo_s1; by timeId; run;

data smo_s2; set mylib.sm(where=(variableID=2)); run;
proc sort data=smo_s2; by timeId; run;

data smo_s3; set mylib.sm(where=(variableID=3)); run;
proc sort data=smo_s3; by timeId; run;

data smo_s4; set mylib.sm(where=(variableID=4)); run;
proc sort data=smo_s4; by timeId; run;

The following statements create a relevant data table, combine_s3, in the Work library to record the smoothing estimates and actual values of OutTemp. Then they draw a plot to compare the smoothing estimates to the actual values at each time step. The plot is shown in Figure 38, where the shadow band indicates the range from the 2.5th to the 97.5th percentiles of the smoothing estimates.

data combine_s3;
   set smo_s3;
   set hvacSystem;
run;

proc sgplot data=combine_s3;
   band x=t upper=P_2 lower=P_1 /transparency=.3;
   series x=Time y=OT /legendlabel='Actual Value' lineattrs=(color=red);
   series x=Time y=Q2/ legendlabel='Smoothing Median'
      lineattrs=(color=blue pattern=shortdash);
run;

Figure 38: Smoothing Estimates vs. Actual Values, OutTemp

Smoothing Estimates vs. Actual Values, OutTemp


The following statements create a relevant data table, combine_s4, in the Work library to record the smoothing estimates and actual values of InTemp. Then they draw a plot to compare the smoothing estimates to the actual values at each time step. The plot is shown in Figure 39, where the shadow band indicates the range from the 2.5th to the 97.5th percentiles of the smoothing estimates.

data combine_s4;
   set smo_s4;
   set hvacSystem;
run;

proc sgplot data=combine_s4;
   band x=t upper=P_2 lower=P_1 /transparency=.3;
   series x=Time y=IT /legendlabel='Actual Value' lineattrs=(color=red);
   series x=Time y=Q2/ legendlabel='Smoothing Median'
      lineattrs=(color=blue pattern=shortdash);
run;

Figure 39: Smoothing Estimates vs. Actual Values, InTemp

Smoothing Estimates vs. Actual Values, InTemp


Figure 38 and Figure 39 show both the outer temperature and inner temperature are accurately estimated by the model.

For the category variables, OutSensorStatus and InSensorStatus, the smoothing estimates of the frequency of the work status (WORK: 1) are used to compare the actual values. The following statements create a relevant data table, combine_s1, in the Work library to record the smoothing estimates and actual values of the category variable OutSensorStatus. Then they draw a plot to compare the smoothing estimates to the actual values at each time step. The plot, which is shown in Figure 40, indicates that the hidden outer sensor status is successfully decoded by the model.

data combine_s1;
   set smo_s1;
   set hvacSystem;
run;

proc sgplot data=combine_s1;
   series x=Time y=OS;
   series x=Time y=cat_2;
run;

Figure 40: Smoothing Estimates vs. Actual Values, OutSensorStatus

Smoothing Estimates vs. Actual Values, OutSensorStatus


The following statements create a relevant data table, combine_s2, in the Work library to record the smoothing estimates and actual values of the category variable InSensorStatus. Then they draw a plot to compare the smoothing estimates to the actual values at each time step. The plot, which is shown in Figure 41, indicates that the hidden inner sensor status is successfully decoded by the model.

data combine_s2;
   set smo_s2;
   set hvacSystem;
run;

proc sgplot data=combine_s2;
   series x=Time y=IS;
   series x=Time y=cat_2;
run;

Figure 41: Smoothing Estimates vs. Actual Values, InSensorStatus

Smoothing Estimates vs. Actual Values, InSensorStatus


Last updated: July 09, 2026