def save(self, path=None, as_model=False, overwrite=True, save_format=None, **kwargs): if not path: path = self.weight_path makedirs_from_path(path) if as_model: if self.kind == "T": save.save_tf_model(self.model, path, overwrite=overwrite, save_format=save_format, **kwargs) else: save.save_torch_model(self.model, path, overwrite=overwrite, save_format=save_format, **kwargs) else: if self.kind == "T": save.save_tf_weights(self.model, path, overwrite=overwrite, save_format=save_format) else: save.save_torch_weights(self.model, path, overwrite=overwrite, save_format=save_format)
def train(self, idx_train, idx_val=None, epochs=200, early_stopping=None, verbose=0, save_best=True, weight_path=None, as_model=False, monitor='val_acc', early_stop_metric='val_loss', callbacks=None, **kwargs): """Train the model for the input `idx_train` of nodes or `sequence`. Note: ---------- You must compile your model before training/testing/predicting. Use `model.build()`. Parameters: ---------- idx_train: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence` The index of nodes (or sequence) that will be used during training. idx_val: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence`, optional The index of nodes (or sequence) that will be used for validation. (default :obj: `None`, i.e., do not use validation during training) epochs: Positive integer The number of epochs of training.(default :obj: `200`) early_stopping: Positive integer or None The number of early stopping patience during training. (default :obj: `None`, i.e., do not use early stopping during training) verbose: int in {0, 1, 2, 3, 4} 'verbose=0': not verbose; 'verbose=1': Progbar (one line, detailed); 'verbose=2': Progbar (one line, omitted); 'verbose=3': Progbar (multi line, detailed); 'verbose=4': Progbar (multi line, omitted); (default :obj: 0) save_best: bool Whether to save the best weights (accuracy of loss depend on `monitor`) of training or validation (depend on `validation` is `False` or `True`). (default :bool: `True`) weight_path: String or None The path of saved weights/model. (default :obj: `None`, i.e., `./log/{self.name}_weights`) as_model: bool Whether to save the whole model or weights only, if `True`, the `self.custom_objects` must be speficied if you are using custom `layer` or `loss` and so on. monitor: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for `save_best`. (default :obj: `val_acc`) early_stop_metric: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for early stopping. (default :obj: `val_loss`) callbacks: tensorflow.keras.callbacks. (default :obj: `None`) kwargs: other keyword Parameters. Return: ---------- A `tf.keras.callbacks.History` object. Its `History.history` attribute is a record of training loss values and metrics values at successive epochs, as well as validation loss values and validation metrics values (if applicable). """ raise_if_kwargs(kwargs) if not (isinstance(verbose, int) and 0 <= verbose <= 4): raise ValueError("'verbose=0': not verbose" "'verbose=1': Progbar(one line, detailed), " "'verbose=2': Progbar(one line, omitted), " "'verbose=3': Progbar(multi line, detailed), " "'verbose=4': Progbar(multi line, omitted), " f"but got {verbose}") model = self.model # Check if model has been built if model is None: raise RuntimeError( 'You must compile your model before training/testing/predicting. Use `model.build()`.' ) if isinstance(idx_train, Sequence): train_data = idx_train else: idx_train = asintarr(idx_train) train_data = self.train_sequence(idx_train) self.idx_train = idx_train validation = idx_val is not None if validation: if isinstance(idx_val, Sequence): val_data = idx_val else: idx_val = asintarr(idx_val) val_data = self.test_sequence(idx_val) self.idx_val = idx_val else: monitor = 'acc' if monitor[:3] == 'val' else monitor if not isinstance(callbacks, callbacks_module.CallbackList): callbacks = callbacks_module.CallbackList(callbacks) history = History() callbacks.append(history) if early_stopping: es_callback = EarlyStopping(monitor=early_stop_metric, patience=early_stopping, mode='auto', verbose=kwargs.pop('es_verbose', 1)) callbacks.append(es_callback) if save_best: if not weight_path: weight_path = self.weight_path else: self.weight_path = weight_path makedirs_from_path(weight_path) if not weight_path.endswith(POSTFIX): weight_path = weight_path + POSTFIX mc_callback = ModelCheckpoint(weight_path, monitor=monitor, save_best_only=True, save_weights_only=not as_model, verbose=0) callbacks.append(mc_callback) callbacks.set_model(model) model.stop_training = False callbacks.on_train_begin() if verbose: stateful_metrics = {"acc", 'loss', 'val_acc', 'val_loss', 'time'} if verbose <= 2: progbar = Progbar(target=epochs, verbose=verbose, stateful_metrics=stateful_metrics) print("Training...") begin_time = time.perf_counter() for epoch in range(epochs): if verbose > 2: progbar = Progbar(target=len(train_data), verbose=verbose - 2, stateful_metrics=stateful_metrics) callbacks.on_epoch_begin(epoch) callbacks.on_train_batch_begin(0) loss, accuracy = self.train_step(train_data) training_logs = {'loss': loss, 'acc': accuracy} if validation: val_loss, val_accuracy = self.test_step(val_data) training_logs.update({ 'val_loss': val_loss, 'val_acc': val_accuracy }) val_data.on_epoch_end() callbacks.on_train_batch_end(len(train_data), training_logs) callbacks.on_epoch_end(epoch, training_logs) train_data.on_epoch_end() if verbose: time_passed = time.perf_counter() - begin_time training_logs.update({'time': time_passed}) if verbose > 2: print(f"Epoch {epoch+1}/{epochs}") progbar.update(len(train_data), training_logs.items()) else: progbar.update(epoch + 1, training_logs.items()) if model.stop_training: break callbacks.on_train_end() if save_best: self.load(weight_path, as_model=as_model) self.remove_weights() return history
def train_v2(self, idx_train, idx_val=None, epochs=200, early_stopping=None, verbose=False, save_best=True, weight_path=None, as_model=False, monitor='val_acc', early_stop_metric='val_loss', callbacks=None, **kwargs): """ Train the model for the input `idx_train` of nodes or `sequence`. Note: ---------- You must compile your model before training/testing/predicting. Use `model.build()`. Parameters: ---------- idx_train: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence`. The index of nodes (or sequence) that will be used during training. idx_val: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence`, optional The index of nodes (or sequence) that will be used for validation. (default :obj: `None`, i.e., do not use validation during training) epochs: Positive integer The number of epochs of training.(default :obj: `200`) early_stopping: Positive integer or None The number of early stopping patience during training. (default :obj: `None`, i.e., do not use early stopping during training) verbose: bool Whether to show the training details. (default :obj: `None`) save_best: bool Whether to save the best weights (accuracy of loss depend on `monitor`) of training or validation (depend on `validation` is `False` or `True`). (default :bool: `True`) weight_path: String or None The path of saved weights/model. (default :obj: `None`, i.e., `./log/{self.name}_weights`) as_model: bool Whether to save the whole model or weights only, if `True`, the `self.custom_objects` must be speficied if you are using customized `layer` or `loss` and so on. monitor: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for `save_best`. (default :obj: `val_acc`) early_stop_metric: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for early stopping. (default :obj: `val_loss`) callbacks: tensorflow.keras.callbacks. (default :obj: `None`) kwargs: other keyword Parameters. Return: ---------- A `tf.keras.callbacks.History` object. Its `History.history` attribute is a record of training loss values and metrics values at successive epochs, as well as validation loss values and validation metrics values (if applicable). """ if not tf.__version__ >= '2.2.0': raise RuntimeError( f'This method is only work for tensorflow version >= 2.2.0.') # Check if model has been built if self.model is None: raise RuntimeError( 'You must compile your model before training/testing/predicting. Use `model.build()`.' ) if isinstance(idx_train, Sequence): train_data = idx_train else: idx_train = asintarr(idx_train) train_data = self.train_sequence(idx_train) self.idx_train = idx_train validation = idx_val is not None if validation: if isinstance(idx_val, Sequence): val_data = idx_val else: idx_val = asintarr(idx_val) val_data = self.test_sequence(idx_val) self.idx_val = idx_val else: monitor = 'acc' if monitor[:3] == 'val' else monitor model = self.model if not isinstance(callbacks, callbacks_module.CallbackList): callbacks = callbacks_module.CallbackList(callbacks, add_history=True, add_progbar=True, verbose=verbose, epochs=epochs) if early_stopping: es_callback = EarlyStopping(monitor=early_stop_metric, patience=early_stopping, mode='auto', verbose=kwargs.pop('es_verbose', 0)) callbacks.append(es_callback) if save_best: if not weight_path: weight_path = self.weight_path makedirs_from_path(weight_path) if not weight_path.endswith('.h5'): weight_path += '.h5' mc_callback = ModelCheckpoint(weight_path, monitor=monitor, save_best_only=True, save_weights_only=not as_model, verbose=0) callbacks.append(mc_callback) callbacks.set_model(model) # leave it blank for the future allowed_kwargs = set([]) unknown_kwargs = set(kwargs.keys()) - allowed_kwargs if unknown_kwargs: raise TypeError("Invalid keyword argument(s): %s" % (unknown_kwargs, )) callbacks.on_train_begin() for epoch in range(epochs): callbacks.on_epoch_begin(epoch) callbacks.on_train_batch_begin(0) loss, accuracy = self.train_step(train_data) train_data.on_epoch_end() training_logs = {'loss': loss, 'acc': accuracy} callbacks.on_train_batch_end(0, training_logs) if validation: val_loss, val_accuracy = self.test_step(val_data) training_logs.update({ 'val_loss': val_loss, 'val_acc': val_accuracy }) val_data.on_epoch_end() callbacks.on_epoch_end(epoch, training_logs) if model.stop_training: break callbacks.on_train_end() if save_best: self.load(weight_path, as_model=as_model) remove_tf_weights(weight_path) return model.history
def train(self, idx_train, idx_val=None, epochs=200, early_stopping=None, verbose=0, save_best=True, weight_path=None, as_model=False, monitor='val_acc', early_stop_metric='val_loss', callbacks=None, **kwargs): """Train the model for the input `idx_train` of nodes or `sequence`. Note: ---------- You must compile your model before training/testing/predicting. Use `model.build()`. Parameters: ---------- idx_train: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence` The index of nodes (or sequence) that will be used during training. idx_val: Numpy array-like, `list`, Integer scalar or `graphgallery.Sequence`, optional The index of nodes (or sequence) that will be used for validation. (default :obj: `None`, i.e., do not use validation during training) epochs: Positive integer The number of epochs of training.(default :obj: `200`) early_stopping: Positive integer or None The number of early stopping patience during training. (default :obj: `None`, i.e., do not use early stopping during training) verbose: int in {0, 1, 2} 'verbose=0': not verbose; 'verbose=1': tqdm verbose; 'verbose=2': tensorflow probar verbose; (default :obj: 0) save_best: bool Whether to save the best weights (accuracy of loss depend on `monitor`) of training or validation (depend on `validation` is `False` or `True`). (default :bool: `True`) weight_path: String or None The path of saved weights/model. (default :obj: `None`, i.e., `./log/{self.name}_weights`) as_model: bool Whether to save the whole model or weights only, if `True`, the `self.custom_objects` must be speficied if you are using customized `layer` or `loss` and so on. monitor: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for `save_best`. (default :obj: `val_acc`) early_stop_metric: String One of (val_loss, val_acc, loss, acc), it determines which metric will be used for early stopping. (default :obj: `val_loss`) callbacks: tensorflow.keras.callbacks. (default :obj: `None`) kwargs: other keyword Parameters. Return: ---------- A `tf.keras.callbacks.History` object. Its `History.history` attribute is a record of training loss values and metrics values at successive epochs, as well as validation loss values and validation metrics values (if applicable). """ if not verbose in {0, 1, 2}: raise ValueError( "'verbose=0': not verbose; 'verbose=1': tqdm verbose; " "'verbose=2': tensorflow probar verbose; " f"but got {verbose}") model = self.model # Check if model has been built if model is None: raise RuntimeError( 'You must compile your model before training/testing/predicting. Use `model.build()`.' ) # TODO: add metric names in `model` metric_names = ['loss', 'acc'] callback_metrics = metric_names model.stop_training = False if isinstance(idx_train, Sequence): train_data = idx_train else: idx_train = asintarr(idx_train) train_data = self.train_sequence(idx_train) self.idx_train = idx_train validation = idx_val is not None if validation: if isinstance(idx_val, Sequence): val_data = idx_val else: idx_val = asintarr(idx_val) val_data = self.test_sequence(idx_val) self.idx_val = idx_val callback_metrics = copy.copy(metric_names) callback_metrics += ['val_' + n for n in metric_names] else: monitor = 'acc' if monitor[:3] == 'val' else monitor if not isinstance(callbacks, callbacks_module.CallbackList): callbacks = callbacks_module.CallbackList(callbacks) history = tf_History() callbacks.append(history) if verbose == 2: callbacks.append(ProgbarLogger(stateful_metrics=metric_names[1:])) if early_stopping: es_callback = EarlyStopping(monitor=early_stop_metric, patience=early_stopping, mode='auto', verbose=kwargs.pop('es_verbose', 1)) callbacks.append(es_callback) if save_best: if not weight_path: weight_path = self.weight_path makedirs_from_path(weight_path) if not weight_path.endswith('.h5'): weight_path = weight_path + '.h5' mc_callback = ModelCheckpoint(weight_path, monitor=monitor, save_best_only=True, save_weights_only=not as_model, verbose=0) callbacks.append(mc_callback) callbacks.set_model(model) # TODO: to be improved callback_params = { 'batch_size': None, 'epochs': epochs, 'steps': 1, 'samples': 1, 'verbose': verbose == 2, 'do_validation': validation, 'metrics': callback_metrics, } callbacks.set_params(callback_params) raise_if_kwargs(kwargs) callbacks.on_train_begin() if verbose == 1: pbar = tqdm(range(1, epochs + 1)) else: pbar = range(epochs) for epoch in pbar: callbacks.on_epoch_begin(epoch) callbacks.on_train_batch_begin(0) loss, accuracy = self.train_step(train_data) training_logs = {'loss': loss, 'acc': accuracy} if validation: val_loss, val_accuracy = self.test_step(val_data) training_logs.update({ 'val_loss': val_loss, 'val_acc': val_accuracy }) val_data.on_epoch_end() callbacks.on_train_batch_end(0, training_logs) callbacks.on_epoch_end(epoch, training_logs) if verbose == 1: msg = "<" for key, val in training_logs.items(): msg += f"{key.title()} = {val:.4f} " msg += ">" pbar.set_description(msg) train_data.on_epoch_end() if verbose == 2: print() if model.stop_training: break callbacks.on_train_end() if save_best: self.load(weight_path, as_model=as_model) remove_tf_weights(weight_path) return history