'Evaluates a model on a dataset according to an input metric.
Arguments:
datasets (NervanaDataIterator): dataset to evaluate on.
metric (Cost): what function to evaluate dataset on.
Returns:
Host numpy array: the error of the final layer for the evaluation dataset'

def eval(self, dataset, metric):

    self.initialize(dataset)
    running_error = np.zeros(len(metric.metric_names), dtype=np.float32)
    nprocessed = 0
    dataset.reset()
    if hasattr(dataset, 'seq_length'):
        ndata = (dataset.ndata * dataset.seq_length)
    else:
        ndata = dataset.ndata
    for (x, t) in dataset:
        x = self.fprop(x, inference=True)
        nsteps = ((x.shape[1] // self.be.bsz) if (not isinstance(x, list)) else (x[0].shape[1] // self.be.bsz))
        bsz = min((ndata - nprocessed), self.be.bsz)
        running_error += ((metric(x, t, calcrange=slice(0, (nsteps * bsz))) * nsteps) * bsz)
        nprocessed += (bsz * nsteps)
    running_error /= nprocessed
    return running_error
