Beispiel #1
0
def test_prepareDataTrain(targetSeries, exogenousSeries, forecastHorizon):
    """ Tests Utility.prepareDataTrain """

    if exogenousSeries is not None:
        assert targetSeries.shape[
            0] == exogenousSeries.shape[0] + forecastHorizon

    assert targetSeries.shape[0] > forecastHorizon
    n = targetSeries.shape[0] - forecastHorizon

    X, Y = Utility.prepareDataTrain(targetSeries, exogenousSeries,
                                    forecastHorizon)
    assert n == X.shape[0] == Y.shape[
        0]  # Shapes of features and targets must agree

    # The targets must equal to the target series starting at 'forecastHorizon'
    assert np.array_equal(Y, targetSeries[forecastHorizon:])

    xConstruct = targetSeries[:n]
    if len(xConstruct.shape) == 1:
        xConstruct = np.expand_dims(xConstruct, axis=1)

    if exogenousSeries is not None:
        xConstruct = np.concatenate((xConstruct, exogenousSeries), axis=1)

    # Features must match the concatenation of target series and exo series
    assert np.array_equal(X, xConstruct)
    def evaluate(
            self,
            targetSeries,
            exogenousSeries=None,
            returnPred=False
    ):
        """
        Forecast using the model parameters on the provided data, evaluates
        the forecast result using the loss and returns it

        :param targetSeries: Series of the Target Variable, it
        should be a numpy array of shape
        (numTimesteps + self.forecastHorizon, numTargetVariables).
        numTimesteps is the number of timesteps on which our model must predict,
        the values ahead are for evaluating the predicted results with respect
        to them (i.e. they are true targets for our prediction)
        :param exogenousSeries: Series of exogenous Variables, it should be a
        numpy array of shape (numTimesteps, numExoVariables), it can be None
        only if numExoVariables is 0 in which case the exogenous variables
        are not considered
        :param returnPred: If True, then return predictions along with loss, else
        return on loss
        :return: If True, then return predictions along with loss of the predicted
        and true targets, else return only loss
        """

        logger = GlobalLogger.getLogger()

        logger.log(f'Target Series Shape: {targetSeries.shape}', 2, self.evaluate.__name__)
        if exogenousSeries is not None:
            logger.log(
                f'Exogenous Series Shape: {exogenousSeries.shape}', 2, self.evaluate.__name__
            )

        logger.log('Prepare Data', 1, self.evaluate.__name__)

        assert targetSeries.shape[1] == self.numTargetVariables
        assert Utility.isExoShapeValid(exogenousSeries, self.numExoVariables)

        X, Ytrue = Utility.prepareDataTrain(targetSeries, exogenousSeries, self.forecastHorizon)

        logger.log('Begin Evaluation', 1, self.predict.__name__)
        Ypred = tf.squeeze(self.model.predict(np.expand_dims(X, axis=0), verbose=0), axis=0)
        loss = tf.keras.losses.MeanSquaredError()(
            Ytrue,
            Ypred
        )

        if returnPred:
            return loss, Ypred
        else:
            return loss
Beispiel #3
0
    def prepareDataTrainDNN(
            targetSeries,
            exogenousSeries,
            forecastHorizon,
            lag
    ):
        """
        Prepare Data For Training

        :param targetSeries: Multivariate Series of the Target Variable, it
        should be a numpy array of shape (lag + nTrain + forecastHorizon, numTargetVariables)
        :param exogenousSeries: Series of exogenous Variables, it should be a
        numpy array of shape (lag + nTrain, numTargetVariables),
        it can be None only if numExoVariables is 0 in which case the exogenous variables are not
        considered
        :param forecastHorizon: How much further in the future the model has to
        predict the target series variable
        :param lag: The lag to be considered
        :return: Prepared training data X of shape (nTrain, numTargetVariables + numExoVariables),
        Y of shape (nTrain, numTargetVariables)
        """

        Xtemp, Ytemp = Utility.prepareDataTrain(
            targetSeries,
            exogenousSeries,
            forecastHorizon
        )

        X = []
        Y = Ytemp[lag:]

        for i in range(lag, Xtemp.shape[0]):
            vecLen = (lag + 1) * Xtemp.shape[1]
            vec = np.reshape(Xtemp[i - lag: i + 1, :], (vecLen,))
            X.append(vec)

        X = np.array(X)
        return X, Y
Beispiel #4
0
    def train(self,
              targetSeries,
              sequenceLength,
              exogenousSeries=None,
              numIterations=1,
              optimizer=tf.optimizers.Adam(),
              modelSavePath=None,
              verboseLevel=1,
              returnLosses=True):
        """
        Train the Model Parameters on the provided data
        :param targetSeries: Univariate Series of the Target Variable, it
        should be a numpy array of shape (n + self.forecastHorizon,)
        :param sequenceLength: Length of each training sequence
        :param exogenousSeries: Series of exogenous Variables, it should be a
        numpy array of shape (n, numExoVariables), it can be None only if
        numExoVariables is 0 in which case the exogenous variables are not
        considered
        :param numIterations: Number of iterations of training to be performed
        :return: If returnLosses is True, then numpy array of losses of shape (numSeq,)
        :param optimizer: Optimizer of training the parameters
        :param modelSavePath: Path where to save the model parameters after
        each training an a sequence, if None then parameters are not saved
        :param verboseLevel: Verbose level, 0 is nothing, greater values increases
        the information printed to the console
        :param returnLosses: If True, then losses are returned, else losses are not
        returned
        is returned, else None is returned
        """

        logger = GlobalLogger.getLogger()
        verbose = ConsoleLogger(verboseLevel)

        assert (Utility.isExoShapeValid(exogenousSeries,
                                        self.inputDimension - 1))
        X, Y = Utility.prepareDataTrain(targetSeries, exogenousSeries,
                                        self.forecastHorizon)

        n = X.shape[0]
        logger.log(f'Seq Start Time: {self.windowSize}, Train len: {n}', 2,
                   self.train.__name__)
        assert (self.windowSize < n)

        logger.log('Begin Training', 1, self.train.__name__)

        losses = []

        for iteration in range(numIterations):

            verbose.log(f'begin iteration {iteration}', 1)

            seqStartTime = self.windowSize
            cumulIterLoss = 0.0
            numSeq = 0

            iterStartTime = time.time()
            while seqStartTime < n:
                seqEndTime = min(seqStartTime + sequenceLength, n - 1)

                startTime = time.time()
                loss = self.trainSequence(X, Y, seqStartTime, seqEndTime,
                                          optimizer)
                endTime = time.time()
                timeTaken = endTime - startTime

                cumulIterLoss += loss
                numSeq += 1

                verbose.log(
                    f'start timestep: {seqStartTime}' +
                    f' | end timestep: {seqEndTime}' +
                    f' | time taken: {timeTaken : .2f} sec' +
                    f' | Loss: {loss}', 2)

                seqStartTime += sequenceLength

            iterEndTime = time.time()
            iterTimeTaken = iterEndTime - iterStartTime
            avgIterLoss = cumulIterLoss / numSeq

            verbose.log(
                f'Completed Iteration: {iteration}' +
                f' | time taken: {iterTimeTaken : .2f} sec' +
                f' | Avg Iteration Loss: {avgIterLoss}', 1)

            if returnLosses:
                losses.append(avgIterLoss)

            if modelSavePath is not None:
                logger.log(f'Saving Model at {modelSavePath}', 1,
                           self.train.__name__)
                self.save(modelSavePath)

        self.buildMemory(X, n)

        if returnLosses:
            return np.array(losses)