':type train_data: groundhog dataset object
:param train_data: data iterator used for training
:type valid_data: groundhog dataset object
:param valid_data: data iterator used for validation
:type test_data: groundhog dataset object
:param test_data: data iterator used for testing
:type model: groundhog model object
:param model: the model that is supposed to be trained
:type algo: groundhog trainer object
:param algo: optimization algorithm used to optimized the model
:type state: dictionary (or jobman dictionary)
:param state: dictionary containing various hyper-param choices,
but also the current state of the job (the dictionary is used by
jobman to fill in a psql table)
:type channel: jobman handler
:param channel: jobman handler used to communicate with a psql
server
:type hooks: function or list of functions
:param hooks: list of functions that are called every `hookFreq`
steps to carry on various diagnostics
:type reset: int
:param reset: if larger than 0, the train_data iterator position is
reseted to 0 every `reset` number of updates
:type train_cost: bool
:param train_cost: flag saying if the training error (over the
entire training set) should be computed every time the validation
error is computed
:type validate_postprocess: None or function
:param validate_postprocess: function called on the validation cost
every time before applying the logic of the early stopper'

def __init__(self, train_data, valid_data, test_data, model, algo, state, channel, hooks=None, reset=(-1), train_cost=False, validate_postprocess=None):

    self.train_data = train_data
    self.valid_data = valid_data
    self.test_data = test_data
    self.state = state
    self.channel = channel
    self.model = model
    self.algo = algo
    self.valid_id = 0
    self.old_cost = 1e+21
    self.validate_postprocess = validate_postprocess
    self.patience = state['patience']
    self.train_cost = train_cost
    if (hooks and (not isinstance(hooks, (list, tuple)))):
        hooks = [hooks]
    if (self.state['validFreq'] < 0):
        self.state['validFreq'] = self.train_data.get_length()
        print 'Validation    computed    every', self.state['validFreq']
    elif (self.state['validFreq'] > 0):
        print 'Validation    computed    every', self.state['validFreq']
    if (self.state['trainFreq'] < 0):
        self.state['trainFreq'] = self.train_data.get_length()
        print 'Train    frequency    set    to    ', self.state['trainFreq']
    state['bvalidcost'] = 1e+21
    for (pname, _) in model.properties:
        self.state[pname] = 1e+20
    n_elems = ((state['loopIters'] // state['trainFreq']) + 1)
    self.timings = {}
    for name in self.algo.return_names:
        self.timings[name] = numpy.zeros((n_elems,), dtype='float32')
    n_elems = ((state['loopIters'] // state['validFreq']) + 1)
    for pname in model.valid_costs:
        self.state[('valid' + pname)] = 1e+20
        self.state[('test' + pname)] = 1e+20
        self.timings[('fulltrain' + pname)] = numpy.zeros((n_elems,), dtype='float32')
        self.timings[('valid' + pname)] = numpy.zeros((n_elems,), dtype='float32')
        self.timings[('test' + pname)] = numpy.zeros((n_elems,), dtype='float32')
    if (self.channel is not None):
        self.channel.save()
    self.hooks = hooks
    self.reset = reset
    self.start_time = time.time()
    self.batch_start_time = time.time()
