Time Series Model Package

Example 32.6 Recurrent Neural Network Forecasting

This example illustrates how to use the RNNSPEC object to fit a recurrent neural network forecasting model to the airline passenger data (see Example 32.1 for more information about the airline series).

The following statements perform forecasting by using the LSTM recurrent neural network on the example data set. Specifying the value 12 for the 'NINPUT' argument means that the length of the input subsequence is 12. The value, 12, of the 'NVALIDATION' argument corresponds to the range of the validation period. The STD normalization is imposed. SetY specifies the AIR variable as the target variable. The number of layers is 4, which means that the neural network consists of one input layer, two hidden layers, and one output layer. The number of neurons in each hidden node is 30. When you specify 'ADAM' in the 'ALGORITHM' optimizer option, the stochastic gradient descent method uses the Adam optimization algorithm.

     data mylib.airtrain;
             set sashelp.air;
     run;

     proc tsmodel data=mylib.airtrain nosummary  outlog=mylib.outlog
                     outobj=( outfor = mylib.outfor(replace=YES)
                             outstat = mylib.outstat(replace=YES)
                             outrnnstat = mylib.outrnnstat(replace=YES)
                             outopt = mylib.outopt(replace=YES)
                             );
             var air;
             id date interval=month;
             require tsm;
             submit;
                     declare object tsmmodel(tsm);
                     declare object rnnspec(rnnspec);
                     declare object outrnnstat(tsmrnnstat);
                                     declare object outstat(tsmstat);
                     declare object outopt(tsmoutopt);
                     declare object outfor(tsmfor);
                     rc = rnnSpec.Open( );
                     rc = rnnSpec.SetOption(
                                     'RNNTYPE','LSTM',
                                     'NINPUT', 12,
                                     'NVALIDATION', 12,
                                     'NLAYER', 4,
                                     'NNEURONH',30,
                                     'NORMALIZE', 'STD',
                                     'POSTTRAIN', 'YES',
                                     'SEED', 12345
                                     );
                     rc = rnnSpec.SetOptimizer(
                                     'ALGORITHM','ADAM',
                                     'LEARNINGRATE', 0.1,
                                     'BETA1', 0.8,
                                     'BETA2', 0.9,
                                     'LEARNINGPOLICY', 'STEP',
                                     'STEPSIZE', 5,
                                     'GAMMA', 0.5,
                                     'STAGNATION', 20,
                                     'MINIBATCHSIZE',8,
                                     'WARMUPEPOCHS',15,
                                     'MAXEPOCHS', 100
                                     );
                     rc = rnnspec.Close();
                     rc = tsmmodel.Initialize(rnnspec);
                     rc = tsmmodel.SetY(air);
                     rc = tsmmodel.SetOption('lead', 12);
                     rc = tsmmodel.SetOption('alpha', 0.05);
                     rc = tsmmodel.Run( );if rc < 0 then stop;
                     rc = outfor.Collect(tsmmodel);if rc < 0 then stop;
                     rc = outstat.Collect(tsmmodel);if rc < 0 then stop;
                     rc = outrnnstat.Collect(tsmmodel);if rc < 0 then stop;
                     rc = outopt.Collect(tsmmodel);if rc < 0 then stop;
             endsubmit;
     print outlog;
     run;
data null;
   set mylib.outrnnstat;
   call symputx('optepoch', OPTEPOCH);
run;

proc sgplot data=mylib.outopt;
      series x=epoch y=trnerror/ LegendLabel="Train Error"
            lineattrs=(color=green) markers
            markerattrs=(color=green symbol=diamond size=5);
      series x=epoch y=vlderror/ LegendLabel="Validation Error"
            lineattrs=(color=red) markers
            markerattrs=(color=red size=5);
      refline  &optepoch/ axis=x ;
      yaxis label="Error";
run;

Figure 15 shows the training and validation errors of the optimization history. The vertical reference line shows where the SGD optimum occurs.

Figure 15: Training and Validation Errors at Each Epoch

Training and Validation Errors at Each Epoch


The following statements print the output table that is produced by the TSMFOR collect method:

Output 32.6.1 shows part of the forecast value table of the target series, air, that is produced by the LSTM recurrent neural network. The forecast errors and confidence intervals are also shown in the table.

Output 32.6.1: Forecast Table for Airline Passenger Data

ObsVariable
Name
Time ID ValuesActual ValuesPredicted ValuesPrediction ErrorsPrediction Standard
Errors
Upper Confidence
Limits
Lower Confidence
Limits
140AIRAUG1960606580.5289306625.47106933613.172509395606.34657466554.71128666
141AIRSEP1960508507.431549070.568450927713.172509395533.24919307481.61390507
142AIROCT1960461453.64114387.358856201213.172509395479.4587878427.8234998
143AIRNOV1960390406.93655396-16.9365539613.172509395432.75419795381.11890996
144AIRDEC1960432425.9253546.074645996113.172509395451.742998400.10771
145AIRJAN1961.449.0279541.13.172509395474.8455981423.2103101
146AIRFEB1961.422.8638916.14.926328973452.11895881393.60882439
147AIRMAR1961.440.79019165.16.358533813472.85232876408.72805454
148AIRAPR1961.503.12182617.16.9620821536.36689619469.87675615
149AIRMAY1961.504.62615967.17.142506943538.22485588471.02746345
150AIRJUN1961.569.63146973.17.406278837603.74714935535.5157901
151AIRJUL1961.604.09667969.17.499851019638.39575742569.79760196
152AIRAUG1961.590.88989258.17.553449512625.29402143556.48576373
153AIRSEP1961.543.19689941.17.575083777577.64343064508.75036819
154AIROCT1961.491.10217285.17.60588388525.60907117456.59527453
155AIRNOV1961.430.46447754.17.672488783465.10191907395.82703601
156AIRDEC1961.456.65841675.17.984226252491.90685249421.409981


The following statements generate the plot of the actual values and forecast values:

proc sgplot data=mylib.outfor;
   series x=date y=actual /
          legendlabel="Actual Value" name="actual"
          lineattrs=(color=green) markers
          markerattrs=(color=green size=4);
   series x=date y=predict /
          LegendLabel="Forecast Value" name="forecast"
          lineattrs=(color=red) markers
          markerattrs=(color=red size=4 symbol=triangle);
   xaxis values=('01jan49'd to '01dec61'd by month);
   refline  '01dec59'd/ axis=x;
   refline  '01dec60'd/ axis=x;
   keylegend "actual" "forecast";
   yaxis label="Airline Passenger";
run;

Figure 16 shows the plot of forecasts and their actual values in the training and validation periods. It also shows forecasts of the 12 months after the validation period. The first reference line splits the training and validation periods, and the second reference line indicates the end of the validation period.

Figure 16: Forecast Plot of Airline Passenger Data

Forecast Plot of Airline Passenger Data


Last updated: July 09, 2026