The MBC Procedure

Example 12.1 Storing and Scoring

When you use PROC MBC to fit a model, you can use the STORE statement to save the model for later application to a new data table. For example, you can score new observations to find their posterior probabilities of cluster membership for each cluster in the model. This example uses PROC CAS to run the mbcScore action to do this subsequent scoring.

The following statements generate a data table that represents a scenario in product marketing. The different market segments are distinguished by different levels of certain financial characteristics.

Segment 1 is a generally younger group with a higher debt-to-income ratio, and it might be attracted by newer, more luxurious goods. When marketing to this group, you would like to highlight newer lines with higher price points. In contrast, segment 2, with a low debt-to-income ratio and an average age between that of segments 1 and 3, might represent a group of bargain hunters who would prefer a product that offers the best value. The customers in segment 3 have a higher average age and a moderate debt-to-income ratio, and they represent a group that is not interested in luxury items and not strongly motivated by price. Finally, segment 4 represents customers who do not fit into these groups and so might respond to a variety of offers.

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

data mycas.marketdata;
  label moninc  = 'Monthly Income'
        mondebt = 'Monthly Debt'
        tenancy = 'Months at Current Residence'
        ageyrs  = 'Age';

  call streaminit(869884);

  * -- Segment 1 : Young Spenders ------------ ;
  do j = 1 to 1000;
    moninc  = 12 + sqrt(2)    * rand('normal');
    mondebt =  6 + sqrt(1)    * rand('normal');
    tenancy = 18 + sqrt(2)    * rand('normal');
    ageyrs =  30 + sqrt(8)    * rand('normal');
    output;
  end;
  * -- Segment 2 : Middle-Aged Savers -------- ;
  do j = 1 to 3000;
    moninc  = 10 + sqrt(2.5)  * rand('normal');
    mondebt =  2 + sqrt(0.25) * rand('normal');
    tenancy = 24 + sqrt(3)    * rand('normal');
    ageyrs =  40 + sqrt(8)    * rand('normal');
    output;
  end;
  * -- Segment 3 : Comfortably Established --- ;
  do j = 1 to 6000;
    moninc  = 15 + sqrt(2)    * rand('normal');
    mondebt =  3 + sqrt(0.5)  * rand('normal');
    tenancy = 32 + sqrt(4)    * rand('normal');
    ageyrs =  50 + sqrt(5)    * rand('normal');
    output;
  end;
  * -- Segment 4: Defying Classification ----- ;
  do j = 1 to 300;
    moninc  = rand('uniform') * 15 +  5;
    mondebt = rand('uniform') *  9 +  0;
    tenancy = rand('uniform') * 30 + 10;
    ageyrs  = rand('uniform') * 40 + 20;
    output;
  end;
  drop j;
;

The existence of outliers is a good motivation to include a noise component in the model, because the outliers can otherwise distort the cluster structure in the model. You can use the NOISE=YES option to specify this directly. The following statements fit a range of models to these data. Each model includes a noise component.

proc mbc data=mycas.marketdata nclusters=(2 3 4 5) noise=YES seed=1389035719;
  var moninc mondebt tenancy ageyrs;
run;

Output 12.1.1 shows the "Fit Summary" table, indicating that the model with the best fit has three Gaussian clusters and a noise component.

Output 12.1.1: Mean and Covariance Estimates for Selected Model

The MBC Procedure

Model Selection Summary
Covariance
Structure
Number of
Clusters
Noise
Component
Number of
Parameters
-2 Log LAICAICCBIC
VVV3Y46170967171059171059171392
VVV4Y61170965171087171088171529
VVV5Y76170942171094171095171644
VVV2Y31182253182315182315182539


The goal of this analysis is to identify segments within the group of customers, and you can use the OUTPUT statement to label each customer with its most strongly associated segment. The MAXPOST option in the following OUTPUT statement includes the index of the component that has the highest posterior clustering probability for each observation. The indices start at zero for a model that includes a noise component:

proc mbc data=mycas.marketdata nclusters=(2 3 4 5) noise=YES;
  var moninc mondebt tenancy ageyrs;
  output out=mycas.mktscore copyvars=(moninc mondebt tenancy ageyrs) maxpost;
run;

In Output 12.1.2, the "Mixing Estimates" table indicates a mixture component with index 0; this is the noise component.

Output 12.1.2: Mixing Estimates for Selected Model

Mixing Probability Estimates
for Selected Model
Mixing
Component
Mixing
Probability
00.02865
10.58248
20.09776
30.29110


Output 12.1.3 shows the parameter estimates for the selected model.

Output 12.1.3: Parameter Estimates for Selected Model

Parameter Estimates for Selected Model
ClusterVariableMeanCovariance
monincmondebttenancyageyrs
1moninc15.003542.052110.01309-0.001260.02988
 mondebt3.00321 0.508190.057220.00485
 tenancy31.99125  4.01148-0.03269
 ageyrs50.04533   5.03305
2moninc11.968292.124250.024170.07263-0.09442
 mondebt6.01248 1.06665-0.005840.05854
 tenancy17.99029  2.017930.03317
 ageyrs29.99537   7.41317
3moninc9.994632.52433-0.016390.052790.10067
 mondebt1.99783 0.245340.002330.00226
 tenancy24.01474  2.937100.05776
 ageyrs39.91170   8.17630


The clusters that the procedure has identified align well with the segments that are generated in the example.

To market effectively to these different groups, you want to be able to assign a cluster membership score to each potential customer. You can use the STORE statement as follows to save the fitted model for later scoring:

proc mbc data=mycas.marketdata nclusters=(2 3 4 5) noise=YES seed=1389035719;
  var moninc mondebt tenancy ageyrs;
  store mycas.mktgroups;
run;

The mycas.mktgroups store contains a representation of the model that you can apply to a new set of customer data. You can use the mbcScore action to score new observations according to this saved model.

The following statements show a possible set of new data:

data mycas.newcusts;
input moninc    mondebt    tenancy     ageyrs;
datalines;
 7      5      20      35
12      6      20      30
18      4      31      52
10      4      25      37
;

The following statements show how to score the new set by using PROC CAS to invoke the mbcScore action. The mbcScore action call takes several parameters. You specify the new observations to score by using the table parameter. The saved model mycas.mktgroups is specified in the restore parameter. You use the casOut parameter to designate that the data table mycas.newScores will contain the scores for the new data. The copyvars parameter includes the listed input variables in the output data table. The maxpost parameter requests that the variable Group in the output set identify the cluster that has the highest posterior weight for each observation. Finally, you use the nextclus parameter to specify the root of the variable name for each cluster weight.

proc cas;
  action mbc.mbcScore /
    table={name='newcusts'}
    restore={name='mktgroups'}
    casOut={name='newScores', replace=true}
    copyvars={'moninc' , 'mondebt' , 'tenancy' , 'ageyrs'}
    maxpost='group'
    nextclus='cluswt';
  run;
quit;

When the scoring is finished, you can examine the clusterings in the data table mycas.newScores. Output 12.1.4 shows the input data and the resulting weights and clustering.

Output 12.1.4: Weights and Scores for New Data

cluswt0cluswt1cluswt2cluswt3groupmonincmondebttenancyageyrs
0.733500.000000.266500.000000752035
0.000960.000000.999040.0000021262030
0.001760.998240.000000.0000011843152
0.356760.000000.000010.6432331042537


You can use the values in the Group variable to decide what action to take for each customer. You can also consider the strength of the association shown in the variables cluswt0 through cluswt3. In this case, each observation has a strong association with its assigned cluster, but one observation has a noticeable affinity for the noise cluster as well.

Last updated: November 05, 2020