def __init__(self, train_data, model, loss=None, metrics=None, n_epochs=3, batch_size=32, print_every=50, validate_every=-1, dev_data=None, use_cuda=False, save_path=None, optimizer=Adam(lr=0.01, weight_decay=0), check_code_level=0, metric_key=None, sampler=RandomSampler(), use_tqdm=True): super(Trainer, self).__init__() if not isinstance(train_data, DataSet): raise TypeError(f"The type of train_data must be fastNLP.DataSet, got {type(train_data)}.") if not isinstance(model, nn.Module): raise TypeError(f"The type of model must be torch.nn.Module, got {type(model)}.") # check metrics and dev_data if (not metrics) and dev_data is not None: raise ValueError("No metric for dev_data evaluation.") if metrics and (dev_data is None): raise ValueError("No dev_data for evaluations, pass dev_data or set metrics to None. ") # check save_path if not (save_path is None or isinstance(save_path, str)): raise ValueError("save_path can only be None or `str`.") # prepare evaluate metrics = _prepare_metrics(metrics) # parse metric_key # increase_better is True. It means the exp result gets better if the indicator increases. # It is true by default. self.increase_better = True if metric_key is not None: self.increase_better = False if metric_key[0] == "-" else True self.metric_key = metric_key[1:] if metric_key[0] == "+" or metric_key[0] == "-" else metric_key elif len(metrics) > 0: self.metric_key = metrics[0].__class__.__name__.lower().strip('metric') # prepare loss losser = _prepare_losser(loss) # sampler check if not isinstance(sampler, BaseSampler): raise ValueError("The type of sampler should be fastNLP.BaseSampler, got {}.".format(type(sampler))) if check_code_level > -1: _check_code(dataset=train_data, model=model, losser=losser, metrics=metrics, dev_data=dev_data, metric_key=metric_key, check_level=check_code_level, batch_size=min(batch_size, DEFAULT_CHECK_BATCH_SIZE)) self.train_data = train_data self.dev_data = dev_data # If None, No validation. self.model = model self.losser = losser self.metrics = metrics self.n_epochs = int(n_epochs) self.batch_size = int(batch_size) self.use_cuda = bool(use_cuda) self.save_path = save_path self.print_every = int(print_every) self.validate_every = int(validate_every) self.best_metric_indicator = None self.sampler = sampler if isinstance(optimizer, torch.optim.Optimizer): self.optimizer = optimizer else: self.optimizer = optimizer.construct_from_pytorch(self.model.parameters()) self.use_tqdm = use_tqdm if self.use_tqdm: tester_verbose = 0 self.print_every = abs(self.print_every) else: tester_verbose = 1 if self.dev_data is not None: self.tester = Tester(model=self.model, data=self.dev_data, metrics=self.metrics, batch_size=self.batch_size, use_cuda=self.use_cuda, verbose=tester_verbose) self.step = 0 self.start_time = None # start timestamp
def __init__(self, train_data, model, loss=None, metrics=None, n_epochs=3, batch_size=32, print_every=50, validate_every=-1, dev_data=None, use_cuda=False, save_path=None, optimizer=Adam(lr=0.01, weight_decay=0), check_code_level=0, metric_key=None, sampler=RandomSampler(), use_tqdm=True): """ :param DataSet train_data: the training data :param torch.nn.modules.module model: a PyTorch model :param LossBase loss: a loss object :param MetricBase or List[MetricBase] metrics: a metric object or a list of metrics :param int n_epochs: the number of training epochs :param int batch_size: batch size for training and validation :param int print_every: step interval to print next training information. Default: -1(no print). :param int validate_every: step interval to do next validation. Default: -1(validate every epoch). :param DataSet dev_data: the validation data :param use_cuda: :param save_path: file path to save models :param Optimizer optimizer: an optimizer object :param int check_code_level: level of FastNLP code checker. -1: don't check, 0: ignore. 1: warning. 2: strict. `ignore` will not check unused field; `warning` when warn if some field are not used; `strict` means it will raise error if some field are not used. :param str metric_key: a single indicator used to decide the best model based on metric results. It must be one of the keys returned by the FIRST metric in `metrics`. If the overall result gets better if the indicator gets smaller, add a `-` character in front of the string. For example :: metric_key="-PPL" # language model gets better as perplexity gets smaller :param sampler: method used to generate batch data. :param use_tqdm: boolean, use tqdm to show train progress. """ super(Trainer, self).__init__() if not isinstance(train_data, DataSet): raise TypeError( f"The type of train_data must be fastNLP.DataSet, got {type(train_data)}." ) if not isinstance(model, nn.Module): raise TypeError( f"The type of model must be torch.nn.Module, got {type(model)}." ) # check metrics and dev_data if (not metrics) and dev_data is not None: raise ValueError("No metric for dev_data evaluation.") if metrics and (dev_data is None): raise ValueError( "No dev_data for evaluations, pass dev_data or set metrics to None. " ) # check save_path if not (save_path is None or isinstance(save_path, str)): raise ValueError("save_path can only be None or `str`.") # prepare evaluate metrics = _prepare_metrics(metrics) # parse metric_key # increase_better is True. It means the exp result gets better if the indicator increases. # It is true by default. self.increase_better = True if metric_key is not None: self.increase_better = False if metric_key[0] == "-" else True self.metric_key = metric_key[1:] if metric_key[ 0] == "+" or metric_key[0] == "-" else metric_key elif len(metrics) > 0: self.metric_key = metrics[0].__class__.__name__.lower().strip( 'metric') # prepare loss losser = _prepare_losser(loss) # sampler check if not isinstance(sampler, BaseSampler): raise ValueError( "The type of sampler should be fastNLP.BaseSampler, got {}.". format(type(sampler))) if check_code_level > -1: _check_code(dataset=train_data, model=model, losser=losser, metrics=metrics, dev_data=dev_data, metric_key=metric_key, check_level=check_code_level, batch_size=min(batch_size, DEFAULT_CHECK_BATCH_SIZE)) self.train_data = train_data self.dev_data = dev_data # If None, No validation. self.model = model self.losser = losser self.metrics = metrics self.n_epochs = int(n_epochs) self.batch_size = int(batch_size) self.use_cuda = bool(use_cuda) self.save_path = save_path self.print_every = int(print_every) self.validate_every = int(validate_every) self.best_metric_indicator = None self.sampler = sampler if isinstance(optimizer, torch.optim.Optimizer): self.optimizer = optimizer else: self.optimizer = optimizer.construct_from_pytorch( self.model.parameters()) self.use_tqdm = use_tqdm if self.use_tqdm: tester_verbose = 0 self.print_every = abs(self.print_every) else: tester_verbose = 1 if self.dev_data is not None: self.tester = Tester(model=self.model, data=self.dev_data, metrics=self.metrics, batch_size=self.batch_size, use_cuda=self.use_cuda, verbose=tester_verbose) self.step = 0 self.start_time = None # start timestamp
def __init__(self, train_data, model, loss=None, metrics=None, n_epochs=3, batch_size=32, print_every=50, validate_every=-1, dev_data=None, save_path=None, optimizer=Adam(lr=0.01, weight_decay=0), check_code_level=0, metric_key=None, sampler=RandomSampler(), prefetch=False, use_tqdm=True, use_cuda=False, callbacks=None): """ :param DataSet train_data: the training data :param torch.nn.modules.module model: a PyTorch model :param LossBase loss: a loss object :param MetricBase metrics: a metric object or a list of metrics (List[MetricBase]) :param int n_epochs: the number of training epochs :param int batch_size: batch size for training and validation :param int print_every: step interval to print next training information. Default: -1(no print). :param int validate_every: step interval to do next validation. Default: -1(validate every epoch). :param DataSet dev_data: the validation data :param str save_path: file path to save models :param Optimizer optimizer: an optimizer object :param int check_code_level: level of FastNLP code checker. -1: don't check, 0: ignore. 1: warning. 2: strict.\\ `ignore` will not check unused field; `warning` when warn if some field are not used; `strict` means it will raise error if some field are not used. 检查的原理是通过使用很小的batch(默认两个sample)来检查代码是 否能够运行,但是这个过程理论上不会修改任何参数,只是会检查能否运行。但如果(1)模型中存在将batch_size写为某个 固定值的情况;(2)模型中存在累加前向计算次数的,可能会多计算几次。以上情况建议将check_code_level设置为-1 :param str metric_key: a single indicator used to decide the best model based on metric results. It must be one of the keys returned by the FIRST metric in `metrics`. If the overall result gets better if the indicator gets smaller, add "-" in front of the string. For example:: metric_key="-PPL" # language model gets better as perplexity gets smaller :param BaseSampler sampler: method used to generate batch data. :param prefetch: bool, 是否使用额外的进程对产生batch数据。 :param bool use_tqdm: whether to use tqdm to show train progress. :param callbacks: List[Callback]. 用于在train过程中起调节作用的回调函数。比如early stop,negative sampling等可以 通过callback机制实现。 """ super(Trainer, self).__init__() if not isinstance(train_data, DataSet): raise TypeError(f"The type of train_data must be fastNLP.DataSet, got {type(train_data)}.") if not isinstance(model, nn.Module): raise TypeError(f"The type of model must be torch.nn.Module, got {type(model)}.") # check metrics and dev_data if (not metrics) and dev_data is not None: raise ValueError("No metric for dev_data evaluation.") if metrics and (dev_data is None): raise ValueError("No dev_data for evaluations, pass dev_data or set metrics to None. ") # check save_path if not (save_path is None or isinstance(save_path, str)): raise ValueError("save_path can only be None or `str`.") # prepare evaluate metrics = _prepare_metrics(metrics) # parse metric_key # increase_better is True. It means the exp result gets better if the indicator increases. # It is true by default. self.increase_better = True if metric_key is not None: self.increase_better = False if metric_key[0] == "-" else True self.metric_key = metric_key[1:] if metric_key[0] == "+" or metric_key[0] == "-" else metric_key elif len(metrics) > 0: self.metric_key = metrics[0].__class__.__name__.lower().strip('metric') # prepare loss losser = _prepare_losser(loss) # sampler check if not isinstance(sampler, BaseSampler): raise ValueError("The type of sampler should be fastNLP.BaseSampler, got {}.".format(type(sampler))) if check_code_level > -1: _check_code(dataset=train_data, model=model, losser=losser, metrics=metrics, dev_data=dev_data, metric_key=metric_key, check_level=check_code_level, batch_size=min(batch_size, DEFAULT_CHECK_BATCH_SIZE)) self.train_data = train_data self.dev_data = dev_data # If None, No validation. self.model = model self.losser = losser self.metrics = metrics self.n_epochs = int(n_epochs) self.batch_size = int(batch_size) self.use_cuda = bool(use_cuda) self.save_path = save_path self.print_every = int(print_every) self.validate_every = int(validate_every) if validate_every!=0 else -1 self.best_metric_indicator = None self.best_dev_epoch = None self.best_dev_step = None self.best_dev_perf = None self.sampler = sampler self.prefetch = prefetch self.callback_manager = CallbackManager(env={"trainer": self}, callbacks=callbacks) if isinstance(optimizer, torch.optim.Optimizer): self.optimizer = optimizer else: self.optimizer = optimizer.construct_from_pytorch(self.model.parameters()) self.use_tqdm = use_tqdm self.print_every = abs(self.print_every) if self.dev_data is not None: self.tester = Tester(model=self.model, data=self.dev_data, metrics=self.metrics, batch_size=self.batch_size, use_cuda=self.use_cuda, verbose=0) self.step = 0 self.start_time = None # start timestamp