From 64c7ce54682ae404e7566ccd1a9409317ff49230 Mon Sep 17 00:00:00 2001 From: yhcc Date: Tue, 31 May 2022 22:29:58 +0800 Subject: [PATCH 1/3] =?UTF-8?q?1.=E4=BF=AE=E5=A4=8Drich=E5=9C=A8jupyter?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=E4=B8=8D=E6=89=93=E5=8D=B0=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98;2.=E4=BF=AE=E5=A4=8D=E8=8B=A5=E5=B9=B2?= =?UTF-8?q?=E5=85=B6=E4=BB=96bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/callbacks/more_evaluate_callback.py | 3 ++- fastNLP/core/collators/collator.py | 4 +-- fastNLP/core/collators/padders/exceptions.py | 9 ++++++- fastNLP/core/collators/padders/get_padder.py | 17 ++++++------- .../core/collators/padders/jittor_padder.py | 2 +- .../core/collators/padders/torch_padder.py | 2 +- .../core/dataloaders/jittor_dataloader/fdl.py | 2 +- .../core/dataloaders/paddle_dataloader/fdl.py | 2 +- .../core/dataloaders/prepare_dataloader.py | 20 ++++++--------- .../core/dataloaders/torch_dataloader/fdl.py | 12 ++++----- fastNLP/core/utils/rich_progress.py | 25 ++++++++++++++++--- fastNLP/models/torch/seq2seq_generator.py | 2 +- fastNLP/models/torch/seq2seq_model.py | 2 +- .../torch/generator/seq2seq_generator.py | 4 +-- tests/core/collators/test_collator.py | 7 ++++++ .../dataloaders/test_prepare_dataloader.py | 17 ++++++++++++- 16 files changed, 85 insertions(+), 45 deletions(-) diff --git a/fastNLP/core/callbacks/more_evaluate_callback.py b/fastNLP/core/callbacks/more_evaluate_callback.py index e11bacde..690146a2 100644 --- a/fastNLP/core/callbacks/more_evaluate_callback.py +++ b/fastNLP/core/callbacks/more_evaluate_callback.py @@ -81,7 +81,8 @@ class MoreEvaluateCallback(HasMonitorCallback): **kwargs): super(MoreEvaluateCallback, self).__init__(watch_monitor, watch_monitor_larger_better, must_have_monitor=False) - + if watch_monitor is not None and evaluate_every == -1: # 将evaluate_every 弄掉。 + evaluate_every = None if watch_monitor is None and evaluate_every is None: raise RuntimeError("`evaluate_every` and `watch_monitor` cannot be None at the same time.") if watch_monitor is not None and evaluate_every is not None: diff --git a/fastNLP/core/collators/collator.py b/fastNLP/core/collators/collator.py index 7fc11ec8..dab5028c 100644 --- a/fastNLP/core/collators/collator.py +++ b/fastNLP/core/collators/collator.py @@ -176,8 +176,8 @@ class Collator: self.padders = dict(sorted(self.padders.items(), key=lambda x:int(x[0][1:]))) # sort, 这样 _0, _1 能够保持顺序 try: for key, padder in self.padders.items(): - batch = unpack_batch.get(key) - pad_batch[key] = padder(batch) + batch = unpack_batch.get(key) + pad_batch[key] = padder(batch) except BaseException as e: try: logger.error(f"The following exception happens when try to pad the `{key}` field with padder:{padder}:") diff --git a/fastNLP/core/collators/padders/exceptions.py b/fastNLP/core/collators/padders/exceptions.py index 8b08683d..a2b97cbf 100644 --- a/fastNLP/core/collators/padders/exceptions.py +++ b/fastNLP/core/collators/padders/exceptions.py @@ -3,7 +3,8 @@ __all__ = [ 'EleDtypeUnsupportedError', 'EleDtypeDtypeConversionError', 'DtypeUnsupportedError', - "DtypeError" + "DtypeError", + "NoProperPadderError" ] @@ -22,6 +23,12 @@ class DtypeError(BaseException): self.msg = msg +class NoProperPadderError(BaseException): + def __init__(self, msg, *args): + super(NoProperPadderError, self).__init__(msg, *args) + self.msg = msg + + class EleDtypeUnsupportedError(DtypeError): """ 当 batch 中的 element 的类别本身无法 pad 的时候报错。 diff --git a/fastNLP/core/collators/padders/get_padder.py b/fastNLP/core/collators/padders/get_padder.py index 66d2eee2..dfc228a3 100644 --- a/fastNLP/core/collators/padders/get_padder.py +++ b/fastNLP/core/collators/padders/get_padder.py @@ -49,8 +49,7 @@ def get_padder(batch_field:Sequence[Any], pad_val, dtype, backend, field_name)-> f"information please set logger's level to DEBUG." if must_pad: raise InconsistencyError(msg) - logger.debug(msg) - return NullPadder() + raise NoProperPadderError(msg) # 再检查所有的元素 shape 是否一致? shape_lens = set([len(v[0]) for v in catalog.values()]) @@ -60,8 +59,7 @@ def get_padder(batch_field:Sequence[Any], pad_val, dtype, backend, field_name)-> f"information please set logger's level to DEBUG." if must_pad: raise InconsistencyError(msg) - logger.debug(msg) - return NullPadder() + raise NoProperPadderError(msg) # 再检查所有的元素 type 是否一致 try: @@ -74,8 +72,7 @@ def get_padder(batch_field:Sequence[Any], pad_val, dtype, backend, field_name)-> f"information please set logger's level to DEBUG." if must_pad: raise InconsistencyError(msg) - logger.debug(msg) - return NullPadder() + raise NoProperPadderError(msg) depth = depths.pop() shape_len = shape_lens.pop() @@ -131,8 +128,7 @@ def get_padder(batch_field:Sequence[Any], pad_val, dtype, backend, field_name)-> msg = "Does not support pad tensor under nested list. If you need this, please report." if must_pad: raise RuntimeError(msg) - logger.debug(msg) - return NullPadder() + raise NoProperPadderError(msg) except DtypeError as e: msg = f"Fail to get padder for field:{field_name}. " + e.msg + " To view more " \ @@ -140,8 +136,9 @@ def get_padder(batch_field:Sequence[Any], pad_val, dtype, backend, field_name)-> if must_pad: logger.error(msg) raise type(e)(msg=msg) - logger.debug(msg) - return NullPadder() + + except NoProperPadderError as e: + logger.debug(f"{e.msg}") except BaseException as e: raise e diff --git a/fastNLP/core/collators/padders/jittor_padder.py b/fastNLP/core/collators/padders/jittor_padder.py index d85893f1..c9b36b89 100644 --- a/fastNLP/core/collators/padders/jittor_padder.py +++ b/fastNLP/core/collators/padders/jittor_padder.py @@ -188,7 +188,7 @@ def fill_tensor(batch_field, padded_batch, dtype): padded_batch[i, j, :len(content_ii)] = jittor.Var(np.array(content_ii, dtype=dtype)) elif padded_batch.ndim == 4: try: # 应该是图像,所以直接应该就 ok 了。 - padded_batch = np.array(batch_field) + padded_batch = jittor.Var(batch_field) except: for i, content_i in enumerate(batch_field): for j, content_ii in enumerate(content_i): diff --git a/fastNLP/core/collators/padders/torch_padder.py b/fastNLP/core/collators/padders/torch_padder.py index c208adca..911c7d8c 100644 --- a/fastNLP/core/collators/padders/torch_padder.py +++ b/fastNLP/core/collators/padders/torch_padder.py @@ -175,7 +175,7 @@ def fill_tensor(batch_field, padded_batch, dtype): padded_batch[i, j, :len(content_ii)] = torch.tensor(content_ii, dtype=dtype) elif padded_batch.ndim == 4: try: # 应该是图像,所以直接应该就 ok 了。 - padded_batch = np.array(batch_field) + padded_batch = torch.tensor(batch_field) except: for i, content_i in enumerate(batch_field): for j, content_ii in enumerate(content_i): diff --git a/fastNLP/core/dataloaders/jittor_dataloader/fdl.py b/fastNLP/core/dataloaders/jittor_dataloader/fdl.py index 96f6747b..9f1d5e6f 100644 --- a/fastNLP/core/dataloaders/jittor_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/jittor_dataloader/fdl.py @@ -203,7 +203,7 @@ def prepare_jittor_dataloader(ds_or_db, batch_size: int = 16, shuffle: bool = Fa drop_last: bool = False, num_workers: int = 0, buffer_size: int = 512 * 1024 * 1024, stop_grad: bool = True, keep_numpy_array: bool = False, endless: bool = False, collate_fn: Union[None, str, Callable] = "auto", - non_train_batch_size: int = 16) \ + non_train_batch_size: int = None) \ -> Union[Sequence[JittorDataLoader], Dict[str, JittorDataLoader], JittorDataLoader]: """ ``prepare_jittor_dataloader`` 的功能是将输入的单个或多个 dataset 同时转为 ``JittorDataloader``对象, 详见 :class: `~fastNLP.core.dataloaders.JittorDataLoader`。 diff --git a/fastNLP/core/dataloaders/paddle_dataloader/fdl.py b/fastNLP/core/dataloaders/paddle_dataloader/fdl.py index 3f1b6acd..50bac34b 100644 --- a/fastNLP/core/dataloaders/paddle_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/paddle_dataloader/fdl.py @@ -254,7 +254,7 @@ def prepare_paddle_dataloader(ds_or_db, feed_list=None, places=None, num_workers: int = 0, use_buffer_reader: bool = True, use_shared_memory: bool = True, timeout: int = 0, worker_init_fn: Callable = None, persistent_workers=False, - non_train_batch_size: int = 16) \ + non_train_batch_size: int = None) \ -> Union[Sequence[PaddleDataLoader], Dict[str, PaddleDataLoader], PaddleDataLoader]: """ ``prepare_paddle_dataloader`` 的功能是将输入的单个或多个 dataset 同时转为 ``PaddleDataloader``对象, 详见 :class: `~fastNLP.core.dataloaders.PaddleDataLoader`。 diff --git a/fastNLP/core/dataloaders/prepare_dataloader.py b/fastNLP/core/dataloaders/prepare_dataloader.py index 358578fc..f717841d 100644 --- a/fastNLP/core/dataloaders/prepare_dataloader.py +++ b/fastNLP/core/dataloaders/prepare_dataloader.py @@ -6,7 +6,6 @@ from typing import Union, Callable import os import sys -from ..samplers import RandomBatchSampler, RandomSampler from .torch_dataloader import prepare_torch_dataloader from .paddle_dataloader import prepare_paddle_dataloader from .jittor_dataloader import prepare_jittor_dataloader @@ -16,7 +15,7 @@ from ..log import logger def prepare_dataloader(dataset, batch_size: int = 16, shuffle: bool = False, drop_last: bool = False, collate_fn: Union[Callable, str, None] = 'auto', num_workers: int = 0, - seed: int = 0, backend: str = 'auto'): + backend: str = 'auto'): """ 自动创建合适的 ``DataLoader`` 对象。例如,检测当当前环境是 ``torch`` 的,则返回 ``TorchDataLoader`` , 是 ``paddle`` 的则 返回 ``PaddleDataLoader`` 。如果有更多需要定制的参数,请直接使用对应的 ``prepare`` 函数,例如 @@ -43,7 +42,6 @@ def prepare_dataloader(dataset, batch_size: int = 16, shuffle: bool = False, dro * 为 ``None`` 时 使用各个框架的 DataLoader 的默认 ``collate_fn`` 。 :param num_workers: 使用多少进程进行数据的 fetch 。 - :param seed: 使用的随机数种子。 :param backend: 当前支持 ``["auto", "torch", "paddle", "jittor"]`` 四种类型。 * 为 ``auto`` 时 @@ -61,18 +59,14 @@ def prepare_dataloader(dataset, batch_size: int = 16, shuffle: bool = False, dro if backend == 'auto': backend = _get_backend() if backend == 'torch': - batch_sampler = RandomBatchSampler(dataset=dataset, batch_size=batch_size, shuffle=shuffle, - drop_last=drop_last, seed=seed) - return prepare_torch_dataloader(ds_or_db=dataset, batch_sampler=batch_sampler, collate_fn=collate_fn, - num_workers=num_workers, shuffle=False, sampler=None) + return prepare_torch_dataloader(ds_or_db=dataset, batch_sampler=None, collate_fn=collate_fn, + num_workers=num_workers, shuffle=shuffle, sampler=None, + batch_size=batch_size) elif backend == 'paddle': - batch_sampler = RandomBatchSampler(dataset=dataset, batch_size=batch_size, shuffle=shuffle, - drop_last=drop_last, seed=seed) - return prepare_paddle_dataloader(ds_or_db=dataset, batch_sampler=batch_sampler, collate_fn=collate_fn, - num_workers=num_workers) + return prepare_paddle_dataloader(ds_or_db=dataset, batch_sampler=None, collate_fn=collate_fn, + num_workers=num_workers, batch_size=batch_size, shuffle=shuffle) elif backend == 'jittor': - sampler = RandomSampler(dataset=dataset, shuffle=shuffle, seed=seed) - prepare_jittor_dataloader(ds_or_db=dataset, sampler=sampler, collate_fn=collate_fn, + prepare_jittor_dataloader(ds_or_db=dataset, sampler=None, collate_fn=collate_fn, num_workers=num_workers, batch_size=batch_size, shuffle=shuffle, drop_last=drop_last) else: diff --git a/fastNLP/core/dataloaders/torch_dataloader/fdl.py b/fastNLP/core/dataloaders/torch_dataloader/fdl.py index 4e208b3f..0ef98ae2 100644 --- a/fastNLP/core/dataloaders/torch_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/torch_dataloader/fdl.py @@ -222,7 +222,7 @@ def prepare_torch_dataloader(ds_or_db, multiprocessing_context=None, generator=None, prefetch_factor: int = 2, persistent_workers: bool = False, non_train_sampler: Union["Sampler[int]", ReproducibleSampler, UnrepeatedSampler] = None, - non_train_batch_size: int = 16) \ + non_train_batch_size: int = None) \ -> Union[TorchDataLoader, Dict[str, TorchDataLoader], Sequence[TorchDataLoader]]: """ ``prepare_torch_dataloader`` 的功能是将输入的单个或多个 dataset 同时转为 ``TorchDataloader``对象, 详见 :class: `~fastNLP.core.dataloaders.TorchDataLoader`。 @@ -254,13 +254,13 @@ def prepare_torch_dataloader(ds_or_db, :param non_train_batch_size: 非 'train' 数据集的 ``TorchDataLoader`` 批次大小,默认为 ``16`` 且当 batch_sampler 为 None 有效。 :param shuffle: 是否打乱数据集, 默认为 ``False``。 :param sampler: 实现了 __len__() 和 __iter__() 的实例化对象,其 __iter__() 方法每次都会返回 dataset 的一个下标 index , - 默认为None, 当其不为 None 时, shuffle 参数无效。 + 默认为None, 当其不为 None 时, shuffle 参数无效。 :param non_train_sampler: 非 'train' 数据集的的实现了 __len__() 和 __iter__() 的实例化对象,其 __iter__() 方法每次都会返回 dataset 的一个下标 index , - 默认为None, 当其不为 None 时, shuffle 参数无效。 + 默认为None, 当其不为 None 时, shuffle 参数无效。 :param batch_sampler: 实现了 __len__() 和 __iter__() 的实例化对象,,其__iter__() 方法每次都会返回一个 List 对象, List中的值为 - dataset 的下标 index ;默认为 None,当其不为 None 时,bacth_size, sampler, shuffle 参数均失效。 + dataset 的下标 index ;默认为 None,当其不为 None 时,bacth_size, sampler, shuffle 参数均失效。 :param num_workers: 当 ``num_workers > 0`` 时, ``TorchDataLoader`` 会开启 num_workers 个子进程来处理数据, 可以加快 - 数据处理速度,但同时也消耗大量内存。 当 ``num_workers=0`` 时, 不开启子进程。 默认为 ``0``。 + 数据处理速度,但同时也消耗大量内存。 当 ``num_workers=0`` 时, 不开启子进程。 默认为 ``0``。 :param collate_fn: 用于从 dataset 取到的一个 batch 数据进行打包处理的 Callable 函数,其值应该为以下三个: ``[None, "auto", Callable]``. * callate_fn 为 'None' 时,需要注意的是此时传进来的 datset 类型不能为 :class:`~fastNLP.core.dataset.DataSet` , 当 collate_fn 为 ``None`` 时, @@ -273,7 +273,7 @@ def prepare_torch_dataloader(ds_or_db, :param pin_memory: 如果其为 ``True``, 那么 ``TorchDataLoader`` 会在返回数据张量之前将其 copy 到 cud a的 pin memory 中。 :param drop_last: 当 ``drop_last=True`` 时,``TorchDataLoader`` 会扔掉最后一个长度小于 ``batch_size`` 的 batch 数据; - 若 ``drop_last=False`` , 则会返回该 batch 数据。 默认为 ``False`` 。 + 若 ``drop_last=False`` , 则会返回该 batch 数据。 默认为 ``False`` 。 :param timeout: 子进程的输出队列获取数据的超时值 :param worker_init_fn: init 函数,如果不设置为 None ,则将会在每个子进程初始化时调用该函数。 :param multiprocessing_context: 多进程的上下文环境 diff --git a/fastNLP/core/utils/rich_progress.py b/fastNLP/core/utils/rich_progress.py index d8e9d45b..b28bb3f7 100644 --- a/fastNLP/core/utils/rich_progress.py +++ b/fastNLP/core/utils/rich_progress.py @@ -46,7 +46,6 @@ class DummyFRichProgress: class FRichProgress(Progress, metaclass=Singleton): def new_progess(self, *columns: Union[str, ProgressColumn], - console: Optional[Console] = None, # 这里将 auto_refresh 关掉是想要避免单独开启线程,同时也是为了避免pdb的时候会持续刷新 auto_refresh: bool = False, refresh_per_second: float = 10, @@ -81,7 +80,7 @@ class FRichProgress(Progress, metaclass=Singleton): self.expand = expand self.live = Live( - console=console or get_console(), + console=get_console(), auto_refresh=auto_refresh, refresh_per_second=refresh_per_second, transient=transient, @@ -92,6 +91,12 @@ class FRichProgress(Progress, metaclass=Singleton): self.get_time = get_time or self.console.get_time self.print = self.console.print self.log = self.console.log + self.auto_refresh = auto_refresh + self.transient = transient + self.redirect_stdout = redirect_stdout + self.redirect_stderr = redirect_stderr + self.refresh_per_second = refresh_per_second + self._need_renew_live = False return self @@ -125,7 +130,19 @@ class FRichProgress(Progress, metaclass=Singleton): from .tqdm_progress import f_tqdm_progress assert not f_tqdm_progress.not_empty(), "Cannot use rich before tqdm finish loop." - if self.live._started is False: + # 如果需要替换,应该是由于destroy的时候给换掉了 + if self._need_renew_live: + self.live = Live( + console=get_console(), + auto_refresh=self.auto_refresh, + refresh_per_second=self.refresh_per_second, + transient=self.transient, + redirect_stdout=self.redirect_stdout, + redirect_stderr=self.redirect_stderr, + get_renderable=self.get_renderable, + ) + self._need_renew_live = False + if not self.live.is_started: self.start() post_desc = fields.pop('post_desc', '') return super().add_task(description=description, @@ -155,6 +172,8 @@ class FRichProgress(Progress, metaclass=Singleton): setattr(self.live.console, 'line', lambda *args,**kwargs:...) self.live.stop() setattr(self.live.console, 'line', old_line) + # 在 jupyter 的情况下需要替换一下,不然会出不打印的问题。 + self._need_renew_live = True if is_notebook() else False def start(self) -> None: super().start() diff --git a/fastNLP/models/torch/seq2seq_generator.py b/fastNLP/models/torch/seq2seq_generator.py index 9ee723e5..68b405ba 100755 --- a/fastNLP/models/torch/seq2seq_generator.py +++ b/fastNLP/models/torch/seq2seq_generator.py @@ -65,7 +65,7 @@ class SequenceGeneratorModel(nn.Module): if tgt_seq_len is not None: mask = seq_len_to_mask(tgt_seq_len, max_len=tgt_tokens.size(1)) tgt_tokens = tgt_tokens.masked_fill(mask.eq(0), -100) - loss = F.cross_entropy(pred.transpose(1, 2), tgt_tokens) + loss = F.cross_entropy(pred[:, :-1].transpose(1, 2), tgt_tokens[:, 1:]) return {'loss': loss} def evaluate_step(self, src_tokens, src_seq_len=None): diff --git a/fastNLP/models/torch/seq2seq_model.py b/fastNLP/models/torch/seq2seq_model.py index 057fb93b..1420375e 100755 --- a/fastNLP/models/torch/seq2seq_model.py +++ b/fastNLP/models/torch/seq2seq_model.py @@ -59,7 +59,7 @@ class Seq2SeqModel(nn.Module): if tgt_seq_len is not None: mask = seq_len_to_mask(tgt_seq_len, max_len=tgt_tokens.size(1)) tgt_tokens = tgt_tokens.masked_fill(mask.eq(0), -100) - loss = F.cross_entropy(pred.transpose(1, 2), tgt_tokens) + loss = F.cross_entropy(pred[:, :-1].transpose(1, 2), tgt_tokens[:, 1:]) return {'loss': loss} def prepare_state(self, src_tokens, src_seq_len=None): diff --git a/fastNLP/modules/torch/generator/seq2seq_generator.py b/fastNLP/modules/torch/generator/seq2seq_generator.py index cf9c5306..b54eea28 100755 --- a/fastNLP/modules/torch/generator/seq2seq_generator.py +++ b/fastNLP/modules/torch/generator/seq2seq_generator.py @@ -368,13 +368,13 @@ def _beam_search_generate(decoder: Seq2SeqDecoder, tokens=None, state=None, max_ next_scores, ids = _scores.topk(2 * num_beams, dim=1, largest=True, sorted=True) _tokens = _tokens.view(batch_size, num_beams * (num_beams + 1)) next_tokens = _tokens.gather(dim=1, index=ids) # (batch_size, 2*num_beams) - from_which_beam = ids // (num_beams + 1) # (batch_size, 2*num_beams) + from_which_beam = torch.floor(ids / (num_beams + 1)).long() # (batch_size, 2*num_beams) else: scores = F.log_softmax(scores, dim=-1) # (batch_size * num_beams, vocab_size) _scores = scores + beam_scores[:, None] # (batch_size * num_beams, vocab_size) _scores = _scores.view(batch_size, -1) # (batch_size, num_beams*vocab_size) next_scores, ids = torch.topk(_scores, 2 * num_beams, dim=1, largest=True, sorted=True) # (bsz, 2*num_beams) - from_which_beam = ids // vocab_size # (batch_size, 2*num_beams) + from_which_beam = torch.floor(ids / vocab_size).long() # (batch_size, 2*num_beams) next_tokens = ids % vocab_size # (batch_size, 2*num_beams) # 接下来需要组装下一个batch的结果。 diff --git a/tests/core/collators/test_collator.py b/tests/core/collators/test_collator.py index 09ec4af8..8443ef92 100644 --- a/tests/core/collators/test_collator.py +++ b/tests/core/collators/test_collator.py @@ -318,6 +318,13 @@ class TestCollator: with pytest.raises(KeyError): collator.set_pad((1, 2)) + @pytest.mark.torch + def test_torch_4d(self): + collator = Collator(backend='torch') + data = [{'x': [[[0,1], [2,3]]]}, {'x': [[[0,1]]]}] + output = collator(data) + assert output['x'].size() == (2, 1, 2, 2) + @pytest.mark.torch def test_torch_dl(): diff --git a/tests/core/dataloaders/test_prepare_dataloader.py b/tests/core/dataloaders/test_prepare_dataloader.py index 223b7880..be6d5feb 100644 --- a/tests/core/dataloaders/test_prepare_dataloader.py +++ b/tests/core/dataloaders/test_prepare_dataloader.py @@ -2,6 +2,7 @@ import pytest from fastNLP import prepare_dataloader from fastNLP import DataSet +from fastNLP.io import DataBundle @pytest.mark.torch @@ -10,4 +11,18 @@ def test_torch(): ds = DataSet({"x": [[1, 2], [2, 3, 4], [4, 5, 6, 7]] * 10, "y": [1, 0, 1] * 10}) dl = prepare_dataloader(ds, batch_size=2, shuffle=True) for batch in dl: - assert isinstance(batch['x'], torch.Tensor) \ No newline at end of file + assert isinstance(batch['x'], torch.Tensor) + + +@pytest.mark.torch +def test_torch_data_bundle(): + import torch + ds = DataSet({"x": [[1, 2], [2, 3, 4], [4, 5, 6, 7]] * 10, "y": [1, 0, 1] * 10}) + dl = DataBundle() + dl.set_dataset(dataset=ds, name='train') + dl.set_dataset(dataset=ds, name='test') + dls = prepare_dataloader(dl, batch_size=2, shuffle=True) + for dl in dls.values(): + for batch in dl: + assert isinstance(batch['x'], torch.Tensor) + assert batch['x'].size(0) == 2 From e55ca8a1d1eb94bf3bc40cd6c598ce5e17f60e3f Mon Sep 17 00:00:00 2001 From: lxr-tech <1838593642@qq.com> Date: Tue, 31 May 2022 23:25:01 +0800 Subject: [PATCH 2/3] update example-12 lxr 220531 --- tutorials/fastnlp_tutorial_2.ipynb | 2 +- tutorials/fastnlp_tutorial_3.ipynb | 16 +- tutorials/fastnlp_tutorial_4.ipynb | 10 +- tutorials/fastnlp_tutorial_5.ipynb | 59 ++ tutorials/fastnlp_tutorial_6.ipynb | 59 ++ tutorials/fastnlp_tutorial_7.ipynb | 59 ++ tutorials/fastnlp_tutorial_8.ipynb | 59 ++ tutorials/fastnlp_tutorial_e1.ipynb | 14 +- tutorials/fastnlp_tutorial_e2.ipynb | 734 ++++++++++++++++++++++--- tutorials/figures/E2-fig-pet-model.png | Bin 0 -> 57162 bytes 10 files changed, 916 insertions(+), 96 deletions(-) create mode 100644 tutorials/fastnlp_tutorial_5.ipynb create mode 100644 tutorials/fastnlp_tutorial_6.ipynb create mode 100644 tutorials/fastnlp_tutorial_7.ipynb create mode 100644 tutorials/fastnlp_tutorial_8.ipynb create mode 100644 tutorials/figures/E2-fig-pet-model.png diff --git a/tutorials/fastnlp_tutorial_2.ipynb b/tutorials/fastnlp_tutorial_2.ipynb index 3aa27c86..4ee9579f 100644 --- a/tutorials/fastnlp_tutorial_2.ipynb +++ b/tutorials/fastnlp_tutorial_2.ipynb @@ -867,7 +867,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.7.13" }, "pycharm": { "stem_cell": { diff --git a/tutorials/fastnlp_tutorial_3.ipynb b/tutorials/fastnlp_tutorial_3.ipynb index 353e4645..172e1232 100644 --- a/tutorials/fastnlp_tutorial_3.ipynb +++ b/tutorials/fastnlp_tutorial_3.ipynb @@ -29,13 +29,7 @@ "\n", "### 1.1 dataloader 的职责描述\n", "\n", - "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前,还存在其他的一些模块,负责例如对文本数据\n", - "\n", - "  进行补零对齐,即 **核对器`collator`模块**,进行分词标注,即 **分词器`tokenizer`模块**\n", - "\n", - "  本节将对`fastNLP`中的核对器`collator`等展开介绍,分词器`tokenizer`将在下一节中详细介绍\n", - "\n", - "在`fastNLP 0.8`中,**核对器`collator`模块负责文本序列的补零对齐**,通过" + "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前" ] }, { @@ -45,13 +39,7 @@ "source": [ "### 1.2 dataloader 的基本使用\n", "\n", - "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前,还存在其他的一些模块,负责例如对文本数据\n", - "\n", - "  进行补零对齐,即 **核对器`collator`模块**,进行分词标注,即 **分词器`tokenizer`模块**\n", - "\n", - "  本节将对`fastNLP`中的核对器`collator`等展开介绍,分词器`tokenizer`将在下一节中详细介绍\n", - "\n", - "在`fastNLP 0.8`中,**核对器`collator`模块负责文本序列的补零对齐**,通过" + "在`fastNLP 0.8`中,在数据加载模块`DataLoader`之前," ] }, { diff --git a/tutorials/fastnlp_tutorial_4.ipynb b/tutorials/fastnlp_tutorial_4.ipynb index 532118b0..3e148bf3 100644 --- a/tutorials/fastnlp_tutorial_4.ipynb +++ b/tutorials/fastnlp_tutorial_4.ipynb @@ -5,21 +5,21 @@ "id": "fdd7ff16", "metadata": {}, "source": [ - "# T4. model 的搭建与 driver 的概念\n", + "# T4. trainer 和 evaluator 的深入介绍(一)\n", "\n", - "  1   fastNLP 中预训练模型的使用\n", + "  1   fastNLP 结合 pytorch 搭建模型\n", " \n", "    1.1   \n", "\n", "    1.2   \n", "\n", - "  2   fastNLP 中使用 Pytorch 搭建模型\n", + "  2   fastNLP 中的 driver 与 device\n", "\n", "    2.1   \n", "\n", "    2.2   \n", "\n", - "  3   fastNLP 中的 driver\n", + "  3   fastNLP 中 trainer 的补充介绍\n", "\n", "    3.1   \n", "\n", @@ -51,7 +51,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/tutorials/fastnlp_tutorial_5.ipynb b/tutorials/fastnlp_tutorial_5.ipynb new file mode 100644 index 00000000..1e41a36e --- /dev/null +++ b/tutorials/fastnlp_tutorial_5.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T5. fastNLP 与 paddle 或 jittor 的结合\n", + "\n", + "  1   fastNLP 结合 paddle 训练模型\n", + " \n", + "    1.1   \n", + "\n", + "    1.2   \n", + "\n", + "  2   fastNLP 结合 jittor 训练模型\n", + "\n", + "    2.1   \n", + "\n", + "    2.2   \n", + "\n", + "  3   fastNLP 实现 paddle 与 pytorch 互转\n", + "\n", + "    3.1   \n", + "\n", + "    3.2   " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_6.ipynb b/tutorials/fastnlp_tutorial_6.ipynb new file mode 100644 index 00000000..bd4b37ed --- /dev/null +++ b/tutorials/fastnlp_tutorial_6.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T6. trainer 和 evaluator 的深入介绍(二)\n", + "\n", + "  1   fastNLP 中预定义模型 models\n", + " \n", + "    1.1   \n", + "\n", + "    1.2   \n", + "\n", + "  2   fastNLP 中预定义模型 modules\n", + " \n", + "    2.1   \n", + "\n", + "    2.2   \n", + "\n", + "  3   fastNLP 中的更多 metric 类型\n", + "\n", + "    3.1   \n", + "\n", + "    3.2   " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_7.ipynb b/tutorials/fastnlp_tutorial_7.ipynb new file mode 100644 index 00000000..0a7d6922 --- /dev/null +++ b/tutorials/fastnlp_tutorial_7.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T7. callback 自定义训练过程\n", + "\n", + "  1   \n", + " \n", + "    1.1   \n", + "\n", + "    1.2   \n", + "\n", + "  2   \n", + "\n", + "    2.1   \n", + "\n", + "    2.2   \n", + "\n", + "  3   \n", + "\n", + "    3.1   \n", + "\n", + "    3.2   " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_8.ipynb b/tutorials/fastnlp_tutorial_8.ipynb new file mode 100644 index 00000000..0664bc41 --- /dev/null +++ b/tutorials/fastnlp_tutorial_8.ipynb @@ -0,0 +1,59 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T8. fastNLP 中的文件读取模块\n", + "\n", + "  1   fastNLP 中的 EmbedLoader 模块\n", + " \n", + "    1.1   \n", + "\n", + "    1.2   \n", + "\n", + "  2   fastNLP 中的 Loader 模块\n", + "\n", + "    2.1   \n", + "\n", + "    2.2   \n", + "\n", + "  3   fastNLP 中的 Pipe 模块\n", + "\n", + "    3.1   \n", + "\n", + "    3.2   " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08752c5a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tutorials/fastnlp_tutorial_e1.ipynb b/tutorials/fastnlp_tutorial_e1.ipynb index 6ec04cb4..8897c800 100644 --- a/tutorials/fastnlp_tutorial_e1.ipynb +++ b/tutorials/fastnlp_tutorial_e1.ipynb @@ -6,7 +6,7 @@ "source": [ "  从这篇开始,我们将开启**`fastNLP v0.8 tutorial`的`example`系列**,在接下来的\n", "\n", - "  每篇`tutorial`里,我们将会介绍`fastNLP v0.8`在一些自然语言处理任务上的应用" + "  每篇`tutorial`里,我们将会介绍`fastNLP v0.8`在自然语言处理任务上的应用实例" ] }, { @@ -82,9 +82,9 @@ "\n", "  包含9个数据集,各语料的语言均为英语,涉及多个自然语言理解`NLU`任务,包括\n", "\n", - "    **`CoLA`**,文本分类任务,预测单句语法正误分类;**`SST2`**,文本分类任务,预测单句情感二分类\n", + "    **`CoLA`**,文本分类任务,预测单句语法正误分类;**`SST-2`**,文本分类任务,预测单句情感二分类\n", "\n", - "    **`MRPC`**,句对分类任务,预测句对语义一致性;**`STSB`**,相似度打分任务,预测句对语义相似度回归\n", + "    **`MRPC`**,句对分类任务,预测句对语义一致性;**`STS-B`**,相似度打分任务,预测句对语义相似度回归\n", "\n", "    **`QQP`**,句对分类任务,预测问题对语义一致性;**`MNLI`**,文本推理任务,预测句对蕴含/矛盾/中立预测\n", "\n", @@ -216,15 +216,15 @@ "\n", "  即使用较小的、不区分大小写的数据集,**对`bert-base`进行知识蒸馏后的版本**,结构上\n", "\n", - "  模型包含1个编码层、6个自注意力层,详解见本篇末尾,更多细节请参考[DistilBert论文](https://arxiv.org/pdf/1910.01108.pdf)\n", + "  包含**1个编码层**、**6个自注意力层**,**参数量`66M`**,详解见本篇末尾,更多请参考[DistilBert论文](https://arxiv.org/pdf/1910.01108.pdf)\n", "\n", - "首先,通过从`transformers`库中导入`AutoTokenizer`模块,使用`from_pretrained`函数初始化\n", + "首先,通过从`transformers`库中导入**`AutoTokenizer`模块**,**使用`from_pretrained`函数初始化**\n", "\n", "  此处的`use_fast`表示是否使用`tokenizer`的快速版本;尝试序列化示例数据,检查加载结果\n", "\n", - "  需要注意的是,处理后返回的两个键值,`'input_ids'`表示原始文本对应的词素编号序列\n", + "  需要注意的是,处理后返回的两个键值,**`'input_ids'`**表示原始文本对应的词素编号序列\n", "\n", - "    `'attention_mask'`表示自注意力运算时的掩模(标上`0`的部分对应`padding`的内容" + "    **`'attention_mask'`**表示自注意力运算时的掩模(标上`0`的部分对应`padding`的内容" ] }, { diff --git a/tutorials/fastnlp_tutorial_e2.ipynb b/tutorials/fastnlp_tutorial_e2.ipynb index 93143090..c8f4b7dc 100644 --- a/tutorials/fastnlp_tutorial_e2.ipynb +++ b/tutorials/fastnlp_tutorial_e2.ipynb @@ -25,31 +25,53 @@ "\n", "    将首先简单介绍提示学习模型的研究,以及与`fastNLP v0.8`结合的优势\n", "\n", - "**`prompt`**,**提示词、提词器**,最早出自**`PET`**,\n", + "**`prompt`**,**提示词**,最早出自论文[Exploiting Cloze Questions for Few Shot TC and NLI](https://arxiv.org/pdf/2001.07676.pdf)中的**`PET`模型**\n", "\n", - "  \n", + "    全称 **`Pattern-Exploiting Training`**,虽然文中并没有提到**`prompt`的说法,但仍视为其开山之作\n", "\n", - "**`prompt-based tuning`**,**基于提示的微调**,描述\n", + "  其大致思路包括,对于文本分类任务,假定输入文本为,后来被称`prompt`,后来被称`verbalizer`,\n", "\n", - "  **`prompt-based model`**,**基于提示的模型**\n", + "  其主要贡献在于,\n", "\n", - "**`prompt-based model`**,**基于提示的模型**,举例\n", + "\n", "\n", - "  案例一:**`P-Tuning v1`**\n", + "**`prompt-based tuning`**,**基于提示的微调**,\n", "\n", - "  案例二:**`PromptTuning`**\n", + "  xxxx,更多参考[prompt综述](https://arxiv.org/pdf/2107.13586.pdf)\n", "\n", - "  案例三:**`PrefixTuning`**\n", + "    以下列举些经典的`prompt-based tuning`案例,简单地介绍下`prompt-based tuning`的脉络\n", "\n", - "  案例四:**`SoftPrompt`**\n", + "  案例一:**`P-Tuning v1`**,详细内容参考[P-Tuning-v1论文](https://arxiv.org/pdf/2103.10385.pdf)\n", "\n", - "使用`fastNLP v0.8`实现`prompt-based model`的优势\n", + "    其主要贡献在于,\n", "\n", - "  \n", + "    其方法大致包括,\n", "\n", - "  本示例仍使用了`tutorial-E1`的`SST2`数据集,将`bert-base-uncased`作为基础模型\n", + "  案例二:**`PromptTuning`**,详细内容参考[PromptTuning论文](https://arxiv.org/pdf/2104.08691.pdf)\n", "\n", - "    在后续实现中,意图通过将连续的`prompt`与`model`拼接,解决`SST2`二分类任务" + "    其主要贡献在于,\n", + "\n", + "    其方法大致包括,\n", + "\n", + "  案例三:**`PrefixTuning`**,详细内容参考[PrefixTuning论文](https://arxiv.org/pdf/2101.00190.pdf)\n", + "\n", + "    其主要贡献在于,\n", + "\n", + "    其方法大致包括,\n", + "\n", + "通过上述介绍可以发现`prompt-based tuning`只是模型微调方式,独立于预训练模型基础`backbone`\n", + "\n", + "  目前,加载预训练模型的主流方法是使用`transformers`模块,而实现微调的框架则\n", + "\n", + "    可以是`pytorch`、`paddle`、`jittor`等,而不同框架间又存在不兼容的问题\n", + "\n", + "  因此,**使用`fastNLP v0.8`实现`prompt-based tuning`**,可以**很好地解决`paddle`等框架**\n", + "\n", + "    **和`transformers`模块之间的桥接**(`transformers`模块基于`pytorch`实现)\n", + "\n", + "本示例仍使用了`tutorial-E1`的`SST2`数据集、`distilbert-base-uncased`模型(便于比较\n", + "\n", + "  使用`pytorch`框架,通过将连续的`prompt`与`model`拼接,解决`SST2`二分类任务" ] }, { @@ -98,7 +120,7 @@ "print(transformers.__version__)\n", "\n", "task = 'sst2'\n", - "model_checkpoint = 'bert-base-uncased'" + "model_checkpoint = 'distilbert-base-uncased' # 'bert-base-uncased'" ] }, { @@ -111,20 +133,32 @@ "\n", "    以下首先简述`P-Tuning v2`的论文原理,并由此引出`fastNLP v0.8`的代码实践\n", "\n", - "`P-Tuning v2`出自论文 [Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks](https://arxiv.org/pdf/2110.07602.pdf)\n", + "**`P-Tuning v2`**出自论文[Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks](https://arxiv.org/pdf/2110.07602.pdf)\n", + "\n", + "  其主要贡献在于,**在`PrefixTuning`等深度提示学习基础上**,**提升了其在分类标注等`NLU`任务的表现**\n", + "\n", + "    并使之在中等规模模型,主要是**参数量在`100M-1B`区间的模型上**,**获得与全参数微调相同的效果**\n", + "\n", + "  其结构如图所示,通过**在输入序列的分类符`[CLS]`之前**,**加入前缀序列**(**序号对应嵌入是待训练的连续值向量**\n", + "\n", + "    **刺激模型在新任务下**,从`[CLS]`对应位置,**输出符合微调任务的输出**,从而达到适应微调任务的目的\n", + "\n", + "\n", "\n", - "  其主要贡献在于,在`PrefixTuning`等深度提示学习基础上,提升了其在分类标注等`NLU`任务的表现\n", + "本示例使用`bert-base-uncased`模型,作为`P-Tuning v2`的基础`backbone`,设置`requires_grad=False`\n", "\n", - "    并使之在中等规模模型,主要是参数量在`100M-1B`区间的模型上,获得与全参数微调相同的效果\n", + "    固定其参数不参与训练,**设置`pre_seq_len`长的`prefix_tokens`作为输入的提示前缀序列**\n", "\n", - "  其结构如图所示,\n", + "  **使用基于`nn.Embedding`的`prefix_encoder`为提示前缀嵌入**,通过`get_prompt`函数获取,再将之\n", "\n", - "" + "    拼接至批量内每笔数据前得到`inputs_embeds`,同时更新自注意力掩模`attention_mask`\n", + "\n", + "  将`inputs_embeds`、`attention_mask`和`labels`输入`backbone`,**得到输出包括`loss`和`logits`**" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -178,24 +212,24 @@ "source": [ "接着,通过确定分类数量初始化模型实例,同时调用`torch.optim.AdamW`模块初始化优化器\n", "\n", - "  根据`P-Tuning v2`论文:*Generally, simple classification tasks prefer shorter prompts (less than 20)*\n", + "  根据`P-Tuning v2`论文:*`Generally, simple classification tasks prefer shorter prompts (less than 20)`*\n", "\n", "  此处`pre_seq_len`参数设定为`20`,学习率相应做出调整,其他内容和`tutorial-E1`中的内容一致" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertForSequenceClassification: ['cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias', 'cls.seq_relationship.bias']\n", - "- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", - "- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", - "Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight']\n", + "Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForSequenceClassification: ['vocab_layer_norm.bias', 'vocab_layer_norm.weight', 'vocab_projector.weight', 'vocab_transform.bias', 'vocab_transform.weight', 'vocab_projector.bias']\n", + "- This IS expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "- This IS NOT expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['pre_classifier.weight', 'classifier.weight', 'pre_classifier.bias', 'classifier.bias']\n", "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" ] } @@ -225,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": { "scrolled": false }, @@ -240,7 +274,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b72eeebd34354a88a99b2e07ec9a86df", + "model_id": "21cbd92c3397497d84dc10f017ec96f4", "version_major": 2, "version_minor": 0 }, @@ -262,30 +296,17 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-18ec0e709f05e61e.arrow\n", - "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-e2f02ee7442ad73e.arrow\n" + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-294e481a713c5754.arrow\n", + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-ed9d9258aaf0fb54.arrow\n", + "Loading cached processed dataset at /remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad/cache-f44c5576b89f9e6b.arrow\n" ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d15505d825b34f649b719f1ff0d56114", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/2 [00:00[22:53:00] INFO Running evaluator sanity check for 2 batches. trainer.py:592\n", + "\n" + ], + "text/plain": [ + "\u001b[2;36m[22:53:00]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches. \u001b]8;id=406635;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=951504;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.540625,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 173.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.540625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m173.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.5,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 160.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.5\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.509375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 163.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.509375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m163.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.634375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 203.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.634375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m203.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.6125,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 196.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.6125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m196.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.675,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 216.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.675\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m216.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.64375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 206.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.64375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m206.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.665625,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 213.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.665625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m213.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.659375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 211.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.659375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m211.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.696875,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 223.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.696875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m223.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "trainer.run(num_eval_batch_per_dl=10)" ] @@ -421,14 +976,55 @@ "cell_type": "markdown", "metadata": {}, "source": [ - " " + "可以发现,其效果远远逊色于`fine-tuning`,这是因为`P-Tuning v2`虽然能够适应参数量\n", + "\n", + "  在`100M-1B`区间的模型,但是,**`distilbert-base`的参数量仅为`66M`**,无法触及其下限\n", + "\n", + "另一方面,**`fastNLP v0.8`不支持`jupyter`多卡**,所以无法在笔者的电脑/服务器上,完成\n", + "\n", + "  合适规模模型的学习,例如`110M`的`bert-base`模型,以及`340M`的`bert-large`模型" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "{'acc#acc': 0.737385, 'total#acc': 872.0, 'correct#acc': 643.0}"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
     "trainer.evaluator.run()"
    ]
diff --git a/tutorials/figures/E2-fig-pet-model.png b/tutorials/figures/E2-fig-pet-model.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3c377c08a0ba3199cca4fb3610aa0ad08ce41fb
GIT binary patch
literal 57162
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
JP@(4*^Iw|h0H6Q>

literal 0
HcmV?d00001


From 2d838b8927b438db5773323d950b94ad0457e873 Mon Sep 17 00:00:00 2001
From: lxr-tech <1838593642@qq.com>
Date: Wed, 1 Jun 2022 23:15:21 +0800
Subject: [PATCH 3/3] update tutorial-45 lxr 220601

---
 tutorials/fastnlp_tutorial_0.ipynb  |  786 ++++++++++-
 tutorials/fastnlp_tutorial_2.ipynb  |    4 +-
 tutorials/fastnlp_tutorial_4.ipynb  |  289 +++-
 tutorials/fastnlp_tutorial_5.ipynb  | 1921 ++++++++++++++++++++++++++-
 tutorials/fastnlp_tutorial_6.ipynb  |   18 +-
 tutorials/fastnlp_tutorial_e1.ipynb |  556 +++++++-
 tutorials/fastnlp_tutorial_e2.ipynb |   52 +-
 7 files changed, 3536 insertions(+), 90 deletions(-)

diff --git a/tutorials/fastnlp_tutorial_0.ipynb b/tutorials/fastnlp_tutorial_0.ipynb
index 245eaf91..8312353b 100644
--- a/tutorials/fastnlp_tutorial_0.ipynb
+++ b/tutorials/fastnlp_tutorial_0.ipynb
@@ -15,15 +15,15 @@
     "\n",
     "    1.3   trainer 内部初始化 evaluater\n",
     "\n",
-    "  2   使用 fastNLP 0.8 搭建 argmax 模型\n",
+    "  2   使用 fastNLP 搭建 argmax 模型\n",
     "\n",
     "    2.1   trainer_step 和 evaluator_step\n",
     "\n",
     "    2.2   trainer 和 evaluator 的参数匹配\n",
     "\n",
-    "    2.3   一个实际案例:argmax 模型\n",
+    "    2.3   示例:argmax 模型的搭建\n",
     "\n",
-    "  3   使用 fastNLP 0.8 训练 argmax 模型\n",
+    "  3   使用 fastNLP 训练 argmax 模型\n",
     " \n",
     "    3.1   trainer 外部初始化的 evaluator\n",
     "\n",
@@ -248,7 +248,7 @@
    "id": "f62b7bb1",
    "metadata": {},
    "source": [
-    "### 2.3 一个实际案例:argmax 模型\n",
+    "### 2.3 示例:argmax 模型的搭建\n",
     "\n",
     "下文将通过训练`argmax`模型,简单介绍如何`Trainer`模块的使用方式\n",
     "\n",
@@ -271,7 +271,7 @@
     "\n",
     "class ArgMaxModel(nn.Module):\n",
     "    def __init__(self, num_labels, feature_dimension):\n",
-    "        super(ArgMaxModel, self).__init__()\n",
+    "        nn.Module.__init__(self)\n",
     "        self.num_labels = num_labels\n",
     "\n",
     "        self.linear1 = nn.Linear(in_features=feature_dimension, out_features=10)\n",
@@ -434,7 +434,7 @@
     "\n",
     "  通过`progress_bar`设定进度条格式,默认为`\"auto\"`,此外还有`\"rich\"`、`\"raw\"`和`None`\n",
     "\n",
-    "    但对于`\"auto\"`和`\"rich\"`格式,在notebook中,进度条在训练结束后会被丢弃\n",
+    "    但对于`\"auto\"`和`\"rich\"`格式,在`jupyter`中,进度条会在训练结束后会被丢弃\n",
     "\n",
     "  通过`n_epochs`设定优化迭代轮数,默认为20;全部`Trainer`的全部变量与函数可以通过`dir(trainer)`查询"
    ]
@@ -489,7 +489,7 @@
     "\n",
     "  其中,可以通过参数`num_train_batch_per_epoch`决定每个`epoch`运行多少个`batch`后停止,默认全部\n",
     "\n",
-    "  此外,可以通过`inspect.getfullargspec(trainer.run)`查询`run`函数的全部参数列表"
+    "  `run`函数完成后在`jupyter`中没有输出保留,此外,通过`help(trainer.run)`可以查询`run`函数的详细内容"
    ]
   },
   {
@@ -590,7 +590,7 @@
     "\n",
     "  其中,可以通过参数`num_eval_batch_per_dl`决定每个`evaluate_dataloader`运行多少个`batch`停止,默认全部\n",
     "\n",
-    "  最终,输出形如`{'acc#acc': acc}`的字典,在notebook中,进度条在评测结束后会被丢弃"
+    "  最终,输出形如`{'acc#acc': acc}`的字典,在`jupyter`中,进度条会在评测结束后会被丢弃"
    ]
   },
   {
@@ -603,6 +603,20 @@
     }
    },
    "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
     {
      "data": {
       "text/html": [
@@ -616,11 +630,11 @@
     {
      "data": {
       "text/html": [
-       "
{'acc#acc': 0.37, 'total#acc': 100.0, 'correct#acc': 37.0}\n",
+       "
{'acc#acc': 0.31, 'total#acc': 100.0, 'correct#acc': 31.0}\n",
        "
\n" ], "text/plain": [ - "\u001b[1m{\u001b[0m\u001b[32m'acc#acc'\u001b[0m: \u001b[1;36m0.37\u001b[0m, \u001b[32m'total#acc'\u001b[0m: \u001b[1;36m100.0\u001b[0m, \u001b[32m'correct#acc'\u001b[0m: \u001b[1;36m37.0\u001b[0m\u001b[1m}\u001b[0m\n" + "\u001b[1m{\u001b[0m\u001b[32m'acc#acc'\u001b[0m: \u001b[1;36m0.31\u001b[0m, \u001b[32m'total#acc'\u001b[0m: \u001b[1;36m100.0\u001b[0m, \u001b[32m'correct#acc'\u001b[0m: \u001b[1;36m31.0\u001b[0m\u001b[1m}\u001b[0m\n" ] }, "metadata": {}, @@ -629,7 +643,7 @@ { "data": { "text/plain": [ - "{'acc#acc': 0.37, 'total#acc': 100.0, 'correct#acc': 37.0}" + "{'acc#acc': 0.31, 'total#acc': 100.0, 'correct#acc': 31.0}" ] }, "execution_count": 9, @@ -650,9 +664,9 @@ "\n", "通过在初始化`trainer`实例时加入`evaluate_dataloaders`和`metrics`,可以实现在训练过程中进行评测\n", "\n", - "  通过`progress_bar`同时设定训练和评估进度条格式,在notebook中,在进度条训练结束后会被丢弃\n", + "  通过`progress_bar`同时设定训练和评估进度条格式,在`jupyter`中,在进度条训练结束后会被丢弃\n", "\n", - "  **通过`evaluate_every`设定评估频率**,可以为负数、正数或者函数:\n", + "  但是中间的评估结果仍会保留;**通过`evaluate_every`设定评估频率**,可以为负数、正数或者函数:\n", "\n", "    **为负数时**,**表示每隔几个`epoch`评估一次**;**为正数时**,**则表示每隔几个`batch`评估一次**" ] @@ -687,9 +701,9 @@ "source": [ "通过使用`Trainer`类的`run`函数,进行训练\n", "\n", - "  还可以通过参数`num_eval_sanity_batch`决定每次训练前运行多少个`evaluate_batch`进行评测,默认为2\n", + "  还可以通过**参数`num_eval_sanity_batch`决定每次训练前运行多少个`evaluate_batch`进行评测**,**默认为`2`**\n", "\n", - "  之所以“先评测后训练”,是为了保证训练很长时间的数据,不会在评测阶段出问题,故作此试探性评测" + "  之所以“先评测后训练”,是为了保证训练很长时间的数据,不会在评测阶段出问题,故作此**试探性评测**" ] }, { @@ -702,6 +716,33 @@ } }, "outputs": [ + { + "data": { + "text/html": [ + "
[18:28:25] INFO     Running evaluator sanity check for 2 batches.              trainer.py:592\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[18:28:25]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches. \u001b]8;id=549287;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=645362;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -712,6 +753,490 @@ "metadata": {}, "output_type": "display_data" }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.31,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 31.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.31\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m31.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.33,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 33.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.33\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m33.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.34,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 34.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.34\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m34.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.36,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 36.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.36\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m36.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.36,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 36.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.36\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m36.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.36,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 36.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.36\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m36.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.36,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 36.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.36\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m36.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.36,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 36.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.36\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m36.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.37,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 37.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.37\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m37.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.4,\n",
+       "  \"total#acc\": 100.0,\n",
+       "  \"correct#acc\": 40.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.4\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m100.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m40.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -746,6 +1271,20 @@ "id": "c4e9c619", "metadata": {}, "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -759,7 +1298,7 @@ { "data": { "text/plain": [ - "{'acc#acc': 0.47, 'total#acc': 100.0, 'correct#acc': 47.0}" + "{'acc#acc': 0.4, 'total#acc': 100.0, 'correct#acc': 40.0}" ] }, "execution_count": 12, @@ -773,9 +1312,222 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "db784d5b", "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['__annotations__',\n", + " '__class__',\n", + " '__delattr__',\n", + " '__dict__',\n", + " '__dir__',\n", + " '__doc__',\n", + " '__eq__',\n", + " '__format__',\n", + " '__ge__',\n", + " '__getattribute__',\n", + " '__gt__',\n", + " '__hash__',\n", + " '__init__',\n", + " '__init_subclass__',\n", + " '__le__',\n", + " '__lt__',\n", + " '__module__',\n", + " '__ne__',\n", + " '__new__',\n", + " '__reduce__',\n", + " '__reduce_ex__',\n", + " '__repr__',\n", + " '__setattr__',\n", + " '__sizeof__',\n", + " '__str__',\n", + " '__subclasshook__',\n", + " '__weakref__',\n", + " '_check_callback_called_legality',\n", + " '_check_train_batch_loop_legality',\n", + " '_custom_callbacks',\n", + " '_driver',\n", + " '_evaluate_dataloaders',\n", + " '_fetch_matched_fn_callbacks',\n", + " '_set_num_eval_batch_per_dl',\n", + " '_train_batch_loop',\n", + " '_train_dataloader',\n", + " '_train_step',\n", + " '_train_step_signature_fn',\n", + " 'accumulation_steps',\n", + " 'add_callback_fn',\n", + " 'backward',\n", + " 'batch_idx_in_epoch',\n", + " 'batch_step_fn',\n", + " 'callback_manager',\n", + " 'check_batch_step_fn',\n", + " 'cur_epoch_idx',\n", + " 'data_device',\n", + " 'dataloader',\n", + " 'device',\n", + " 'driver',\n", + " 'driver_name',\n", + " 'epoch_evaluate',\n", + " 'evaluate_batch_step_fn',\n", + " 'evaluate_dataloaders',\n", + " 'evaluate_every',\n", + " 'evaluate_fn',\n", + " 'evaluator',\n", + " 'extract_loss_from_outputs',\n", + " 'fp16',\n", + " 'get_no_sync_context',\n", + " 'global_forward_batches',\n", + " 'has_checked_train_batch_loop',\n", + " 'input_mapping',\n", + " 'kwargs',\n", + " 'larger_better',\n", + " 'load_checkpoint',\n", + " 'load_model',\n", + " 'marker',\n", + " 'metrics',\n", + " 'model',\n", + " 'model_device',\n", + " 'monitor',\n", + " 'move_data_to_device',\n", + " 'n_epochs',\n", + " 'num_batches_per_epoch',\n", + " 'on',\n", + " 'on_after_backward',\n", + " 'on_after_optimizers_step',\n", + " 'on_after_trainer_initialized',\n", + " 'on_after_zero_grad',\n", + " 'on_before_backward',\n", + " 'on_before_optimizers_step',\n", + " 'on_before_zero_grad',\n", + " 'on_evaluate_begin',\n", + " 'on_evaluate_end',\n", + " 'on_exception',\n", + " 'on_fetch_data_begin',\n", + " 'on_fetch_data_end',\n", + " 'on_load_checkpoint',\n", + " 'on_load_model',\n", + " 'on_sanity_check_begin',\n", + " 'on_sanity_check_end',\n", + " 'on_save_checkpoint',\n", + " 'on_save_model',\n", + " 'on_train_batch_begin',\n", + " 'on_train_batch_end',\n", + " 'on_train_begin',\n", + " 'on_train_end',\n", + " 'on_train_epoch_begin',\n", + " 'on_train_epoch_end',\n", + " 'optimizers',\n", + " 'output_mapping',\n", + " 'progress_bar',\n", + " 'run',\n", + " 'run_evaluate',\n", + " 'save_checkpoint',\n", + " 'save_model',\n", + " 'start_batch_idx_in_epoch',\n", + " 'state',\n", + " 'step',\n", + " 'step_evaluate',\n", + " 'total_batches',\n", + " 'train_batch_loop',\n", + " 'train_dataloader',\n", + " 'train_fn',\n", + " 'train_step',\n", + " 'trainer_state',\n", + " 'zero_grad']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dir(trainer)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "953533c4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on method run in module fastNLP.core.controllers.trainer:\n", + "\n", + "run(num_train_batch_per_epoch: int = -1, num_eval_batch_per_dl: int = -1, num_eval_sanity_batch: int = 2, resume_from: str = None, resume_training: bool = True, catch_KeyboardInterrupt=None) method of fastNLP.core.controllers.trainer.Trainer instance\n", + " 该函数是在 ``Trainer`` 初始化后用于真正开始训练的函数;\n", + " \n", + " 注意如果是断点重训的第一次训练,即还没有保存任何用于断点重训的文件,那么其应当置 resume_from 为 None,并且使用 ``CheckpointCallback``\n", + " 去保存断点重训的文件;\n", + " \n", + " :param num_train_batch_per_epoch: 每个 epoch 训练多少个 batch 后停止,*-1* 表示使用 train_dataloader 本身的长度;\n", + " :param num_eval_batch_per_dl: 每个 evaluate_dataloader 验证多少个 batch 停止,*-1* 表示使用 evaluate_dataloader 本身的长度;\n", + " :param num_eval_sanity_batch: 在训练之前运行多少个 evaluation batch 来检测一下 evaluation 的过程是否有错误。为 0 表示不检测;\n", + " :param resume_from: 从哪个路径下恢复 trainer 的状态,注意该值需要为一个文件夹,例如使用 ``CheckpointCallback`` 时帮助您创建的保存的子文件夹;\n", + " :param resume_training: 是否按照 checkpoint 中训练状态恢复。如果为 False,则只恢复 model 和 optimizers 的状态;该参数如果为 ``True``,\n", + " 在下一次断点重训的时候我们会精确到上次训练截止的具体的 sample 进行训练;否则我们只会恢复 model 和 optimizers 的状态,而 ``Trainer`` 中的\n", + " 其余状态都是保持初始化时的状态不会改变;\n", + " :param catch_KeyboardInterrupt: 是否捕获 KeyboardInterrupt;如果该参数为 ``True``,在训练时如果您使用 ``ctrl+c`` 来终止程序,\n", + " ``Trainer`` 不会抛出异常,但是会提前退出,然后 ``trainer.run()`` 之后的代码会继续运行。注意该参数在您使用分布式训练的 ``Driver``\n", + " 时无效,例如 ``TorchDDPDriver``;非分布式训练的 ``Driver`` 下该参数默认为 True;\n", + " \n", + " .. warning::\n", + " \n", + " 注意初始化的 ``Trainer`` 只能调用一次 ``run`` 函数,即之后的调用 ``run`` 函数实际不会运行,因为此时\n", + " ``trainer.cur_epoch_idx == trainer.n_epochs``;\n", + " \n", + " 这意味着如果您需要再次调用 ``run`` 函数,您需要重新再初始化一个 ``Trainer``;\n", + " \n", + " .. note::\n", + " \n", + " 您可以使用 ``num_train_batch_per_epoch`` 来简单地对您的训练过程进行验证,例如,当您指定 ``num_train_batch_per_epoch=10`` 后,\n", + " 每一个 epoch 下实际训练的 batch 的数量则会被修改为 10。您可以先使用该值来设定一个较小的训练长度,在验证整体的训练流程没有错误后,再将\n", + " 该值设定为 **-1** 开始真正的训练;\n", + " \n", + " ``num_eval_batch_per_dl`` 的意思和 ``num_train_batch_per_epoch`` 类似,即您可以通过设定 ``num_eval_batch_per_dl`` 来验证\n", + " 整体的验证流程是否正确;\n", + " \n", + " ``num_eval_sanity_batch`` 的作用可能会让人产生迷惑,其本质和 ``num_eval_batch_per_dl`` 作用一致,但是其只被 ``Trainer`` 使用;\n", + " 并且其只会在训练的一开始使用,意思为:我们在训练的开始时会先使用 ``Evaluator``(如果其不为 ``None``) 进行验证,此时验证的 batch 的\n", + " 数量只有 ``num_eval_sanity_batch`` 个;但是对于 ``num_eval_batch_per_dl`` 而言,其表示在实际的整体的训练过程中,每次 ``Evaluator``\n", + " 进行验证时会验证的 batch 的数量。\n", + " \n", + " 并且,在实际真正的训练中,``num_train_batch_per_epoch`` 和 ``num_eval_batch_per_dl`` 应当都被设置为 **-1**,但是 ``num_eval_sanity_batch``\n", + " 应当为一个很小的正整数,例如 2;\n", + " \n", + " .. note::\n", + " \n", + " 参数 ``resume_from`` 和 ``resume_training`` 的设立是为了支持断点重训功能;仅当 ``resume_from`` 不为 ``None`` 时,``resume_training`` 才有效;\n", + " \n", + " 断点重训的意思为将上一次训练过程中的 ``Trainer`` 的状态保存下来,包括模型和优化器的状态、当前训练过的 epoch 的数量、对于当前的 epoch\n", + " 已经训练过的 batch 的数量、callbacks 的状态等等;然后在下一次训练时直接加载这些状态,从而直接恢复到上一次训练过程的某一个具体时间点的状态开始训练;\n", + " \n", + " fastNLP 将断点重训分为了 **保存状态** 和 **恢复断点重训** 两部分:\n", + " \n", + " 1. 您需要使用 ``CheckpointCallback`` 来保存训练过程中的 ``Trainer`` 的状态;具体详见 :class:`~fastNLP.core.callbacks.CheckpointCallback`;\n", + " ``CheckpointCallback`` 会帮助您把 ``Trainer`` 的状态保存到一个具体的文件夹下,这个文件夹的名字由 ``CheckpointCallback`` 自己生成;\n", + " 2. 在第二次训练开始时,您需要找到您想要加载的 ``Trainer`` 状态所存放的文件夹,然后传入给参数 ``resume_from``;\n", + " \n", + " 需要注意的是 **保存状态** 和 **恢复断点重训** 是互不影响的。\n", + "\n" + ] + } + ], + "source": [ + "help(trainer.run)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bc7cb4a", + "metadata": {}, "outputs": [], "source": [] } diff --git a/tutorials/fastnlp_tutorial_2.ipynb b/tutorials/fastnlp_tutorial_2.ipynb index 4ee9579f..64c4bc8b 100644 --- a/tutorials/fastnlp_tutorial_2.ipynb +++ b/tutorials/fastnlp_tutorial_2.ipynb @@ -281,13 +281,13 @@ "## 2. fastNLP 中的 tokenizer\n", "\n", "### 2.1 PreTrainTokenizer 的提出\n", - "\n", + "\n", "在`fastNLP 0.8`中,**使用`PreTrainedTokenizer`模块来为数据集中的词语进行词向量的标注**\n", "\n", "  需要注意的是,`PreTrainedTokenizer`模块的下载和导入**需要确保环境安装了`transformers`模块**\n", diff --git a/tutorials/fastnlp_tutorial_4.ipynb b/tutorials/fastnlp_tutorial_4.ipynb index 3e148bf3..ee5a0c6b 100644 --- a/tutorials/fastnlp_tutorial_4.ipynb +++ b/tutorials/fastnlp_tutorial_4.ipynb @@ -5,32 +5,292 @@ "id": "fdd7ff16", "metadata": {}, "source": [ - "# T4. trainer 和 evaluator 的深入介绍(一)\n", + "# T4. trainer 和 evaluator 的深入介绍\n", "\n", - "  1   fastNLP 结合 pytorch 搭建模型\n", + "  1   fastNLP 中的更多 metric 类型\n", + "\n", + "    1.1   预定义的 metric 类型\n", + "\n", + "    1.2   自定义的 metric 类型\n", + "\n", + "  2   fastNLP 中 trainer 的补充介绍\n", " \n", - "    1.1   \n", + "    2.1   trainer 的提出构想 \n", "\n", - "    1.2   \n", + "    2.2   trainer 的内部结构\n", "\n", - "  2   fastNLP 中的 driver 与 device\n", + "    2.3   实例:\n", "\n", - "    2.1   \n", + "  3   fastNLP 中的 driver 与 device\n", "\n", - "    2.2   \n", + "    3.1   driver 的提出构想\n", + "\n", + "    3.2   device 与多卡训练" + ] + }, + { + "cell_type": "markdown", + "id": "8d19220c", + "metadata": {}, + "source": [ + "## 1. fastNLP 中的更多 metric 类型\n", "\n", - "  3   fastNLP 中 trainer 的补充介绍\n", + "### 1.1 预定义的 metric 类型\n", "\n", - "    3.1   \n", + "在`fastNLP 0.8`中,除了前几篇`tutorial`中经常见到的**正确率`Accuracy`**,还有其他**预定义的评价标准`metric`**\n", + "\n", + "  包括**所有`metric`的基类`Metric`**、适配`Transformers`中相关模型的正确率`TransformersAccuracy`\n", + "\n", + "    **适用于分类语境下的`F1`值`ClassifyFPreRecMetric`**(其中也包括**召回率`Pre`**、**精确率`Rec`**\n", + "\n", + "    **适用于抽取语境下的`F1`值`SpanFPreRecMetric`**;相关基本信息内容见下表,之后是详细分析\n", + "\n", + "|
代码名称
|
简要介绍
|
代码路径
|\n", + "|:--|:--|:--|\n", + "| `Metric` | 定义`metrics`时继承的基类 | `/core/metrics/metric.py` |\n", + "| `Accuracy` | 正确率,最为常用 | `/core/metrics/accuracy.py` |\n", + "| `TransformersAccuracy` | 正确率,为了兼容`Transformers`中相关模型 | `/core/metrics/accuracy.py` |\n", + "| `ClassifyFPreRecMetric` | 召回率、精确率、F1值,适用于**分类问题** | `/core/metrics/classify_f1_pre_rec_metric.py` |\n", + "| `SpanFPreRecMetric` | 召回率、精确率、F1值,适用于**抽取问题** | `/core/metrics/span_f1_pre_rec_metric.py` |" + ] + }, + { + "cell_type": "markdown", + "id": "fdc083a3", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "source": [ + "大概的描述一下,给出各个正确率的计算公式" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9775ea5e", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "8a22f522", + "metadata": {}, + "source": [ + "### 2.2 自定义的 metric 类型\n", "\n", - "    3.2   " + "在`fastNLP 0.8`中,  给一个案例,训练部分留到trainer部分" ] }, { "cell_type": "code", "execution_count": null, + "id": "d8caba1d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e6247dd", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", "id": "08752c5a", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## 2. fastNLP 中 trainer 的补充介绍\n", + "\n", + "### 2.1 trainer 的提出构想\n", + "\n", + "在`fastNLP 0.8`中,  " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "977a6355", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "69203cdc", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ab1cea7d", + "metadata": {}, + "source": [ + "### 2.2 trainer 的内部结构\n", + "\n", + "在`fastNLP 0.8`中,  \n", + "\n", + "'accumulation_steps', 'add_callback_fn', 'backward', 'batch_idx_in_epoch', 'batch_step_fn',\n", + "'callback_manager', 'check_batch_step_fn', 'cur_epoch_idx', 'data_device', 'dataloader',\n", + "'device', 'driver', 'driver_name', 'epoch_evaluate', 'evaluate_batch_step_fn', 'evaluate_dataloaders',\n", + "'evaluate_every', 'evaluate_fn', 'evaluator', 'extract_loss_from_outputs', 'fp16',\n", + "'get_no_sync_context', 'global_forward_batches', 'has_checked_train_batch_loop',\n", + "'input_mapping', 'kwargs', 'larger_better', 'load_checkpoint', 'load_model', 'marker',\n", + "'metrics', 'model', 'model_device', 'monitor', 'move_data_to_device', 'n_epochs', 'num_batches_per_epoch',\n", + "'on', 'on_after_backward', 'on_after_optimizers_step', 'on_after_trainer_initialized',\n", + "'on_after_zero_grad', 'on_before_backward', 'on_before_optimizers_step', 'on_before_zero_grad',\n", + "'on_evaluate_begin', 'on_evaluate_end', 'on_exception', 'on_fetch_data_begin', 'on_fetch_data_end',\n", + "'on_load_checkpoint', 'on_load_model', 'on_sanity_check_begin', 'on_sanity_check_end',\n", + "'on_save_checkpoint', 'on_save_model', 'on_train_batch_begin', 'on_train_batch_end',\n", + "'on_train_begin', 'on_train_end', 'on_train_epoch_begin', 'on_train_epoch_end',\n", + "'optimizers', 'output_mapping', 'progress_bar', 'run', 'run_evaluate',\n", + "'save_checkpoint', 'save_model', 'start_batch_idx_in_epoch', 'state',\n", + "'step', 'step_evaluate', 'total_batches', 'train_batch_loop', 'train_dataloader', 'train_fn', 'train_step',\n", + "'trainer_state', 'zero_grad'\n", + "\n", + "  run(num_train_batch_per_epoch: int = -1, num_eval_batch_per_dl: int = -1, num_eval_sanity_batch: int = 2, resume_from: str = None, resume_training: bool = True, catch_KeyboardInterrupt=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3c8342e", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d28f2624", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ce6322b4", "metadata": {}, + "source": [ + "### 2.3 实例:\n", + "\n", + "在`fastNLP 0.8`中,  " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43be274f", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c348864c", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "175d6ebb", + "metadata": {}, + "source": [ + "## 3. fastNLP 中的 driver 与 device\n", + "\n", + "### 3.1 driver 的提出构想\n", + "\n", + "在`fastNLP 0.8`中,  " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47100e7a", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0204a223", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "6e723b87", + "metadata": {}, + "source": [ + "### 3.2 device 与多卡训练\n", + "\n", + "在`fastNLP 0.8`中,  " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ad81ac7", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cfb28b1b", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, "outputs": [], "source": [] } @@ -52,6 +312,15 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.13" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "metadata": { + "collapsed": false + }, + "source": [] + } } }, "nbformat": 4, diff --git a/tutorials/fastnlp_tutorial_5.ipynb b/tutorials/fastnlp_tutorial_5.ipynb index 1e41a36e..cb105c89 100644 --- a/tutorials/fastnlp_tutorial_5.ipynb +++ b/tutorials/fastnlp_tutorial_5.ipynb @@ -5,31 +5,1930 @@ "id": "fdd7ff16", "metadata": {}, "source": [ - "# T5. fastNLP 与 paddle 或 jittor 的结合\n", + "# T5. fastNLP 中的预定义模型\n", "\n", - "  1   fastNLP 结合 paddle 训练模型\n", + "  1   fastNLP 中 modules 的介绍\n", " \n", - "    1.1   \n", + "    1.1   modules 模块、models 模块 简介\n", "\n", - "    1.2   \n", + "    1.2   示例一:modules 实现 LSTM 分类\n", "\n", - "  2   fastNLP 结合 jittor 训练模型\n", + "  2   fastNLP 中 models 的介绍\n", + " \n", + "    2.1   示例一:models 实现 CNN 分类\n", "\n", - "    2.1   \n", + "    2.3   示例二:models 实现 BiLSTM 标注" + ] + }, + { + "cell_type": "markdown", + "id": "d3d65d53", + "metadata": {}, + "source": [ + "## 1. fastNLP 中 modules 模块的介绍\n", "\n", - "    2.2   \n", + "### 1.1 modules 模块、models 模块 简介\n", "\n", - "  3   fastNLP 实现 paddle 与 pytorch 互转\n", + "在`fastNLP 0.8`中,**`modules.torch`路径下定义了一些基于`pytorch`实现的基础模块**\n", "\n", - "    3.1   \n", + "    包括长短期记忆网络`LSTM`、条件随机场`CRF`、`transformer`的编解码器模块等,详见下表\n", "\n", - "    3.2   " + "|
代码名称
|
简要介绍
|
代码路径
|\n", + "|:--|:--|:--|\n", + "| `LSTM` | 轻量封装`pytorch`的`LSTM` | `/modules/torch/encoder/lstm.py` |\n", + "| `Seq2SeqEncoder` | 序列变换编码器,基类 | `/modules/torch/encoder/seq2seq_encoder.py` |\n", + "| `LSTMSeq2SeqEncoder` | 序列变换编码器,基于`LSTM` | `/modules/torch/encoder/seq2seq_encoder.py` |\n", + "| `TransformerSeq2SeqEncoder` | 序列变换编码器,基于`transformer` | `/modules/torch/encoder/seq2seq_encoder.py` |\n", + "| `StarTransformer` | `Star-Transformer`的编码器部分 | `/modules/torch/encoder/star_transformer.py` |\n", + "| `VarRNN` | 实现`Variational Dropout RNN` | `/modules/torch/encoder/variational_rnn.py` |\n", + "| `VarLSTM` | 实现`Variational Dropout LSTM` | `/modules/torch/encoder/variational_rnn.py` |\n", + "| `VarGRU` | 实现`Variational Dropout GRU` | `/modules/torch/encoder/variational_rnn.py` |\n", + "| `ConditionalRandomField` | 条件随机场模型 | `/modules/torch/decoder/crf.py` |\n", + "| `Seq2SeqDecoder` | 序列变换解码器,基类 | `/modules/torch/decoder/seq2seq_decoder.py` |\n", + "| `LSTMSeq2SeqDecoder` | 序列变换解码器,基于`LSTM` | `/modules/torch/decoder/seq2seq_decoder.py` |\n", + "| `TransformerSeq2SeqDecoder` | 序列变换解码器,基于`transformer` | `/modules/torch/decoder/seq2seq_decoder.py` |\n", + "| `SequenceGenerator` | 序列生成,封装`Seq2SeqDecoder` | `/models/torch/sequence_labeling.py` |\n", + "| `TimestepDropout` | 在每个`timestamp`上`dropout` | `/modules/torch/dropout.py` |" + ] + }, + { + "cell_type": "markdown", + "id": "89ffcf07", + "metadata": {}, + "source": [ + "  **`models.torch`路径下定义了一些基于`pytorch`、`modules`实现的预定义模型** \n", + "\n", + "    例如基于`CNN`的分类模型、基于`BiLSTM+CRF`的标注模型、基于[双仿射注意力机制](https://arxiv.org/pdf/1611.01734.pdf)的分析模型\n", + "\n", + "    基于`modules.torch`中的`LSTM`/`transformer`编/解码器模块的序列变换/生成模型,详见下表\n", + "\n", + "|
代码名称
|
简要介绍
|
代码路径
|\n", + "|:--|:--|:--|\n", + "| `BiaffineParser` | 句法分析模型,基于双仿射注意力 | `/models/torch/biaffine_parser.py` |\n", + "| `CNNText` | 文本分类模型,基于`CNN` | `/models/torch/cnn_text_classification.py` |\n", + "| `Seq2SeqModel` | 序列变换,基类`encoder+decoder` | `/models/torch/seq2seq_model.py` |\n", + "| `LSTMSeq2SeqModel` | 序列变换,基于`LSTM` | `/models/torch/seq2seq_model.py` |\n", + "| `TransformerSeq2SeqModel` | 序列变换,基于`transformer` | `/models/torch/seq2seq_model.py` |\n", + "| `SequenceGeneratorModel` | 封装`Seq2SeqModel`,结合`SequenceGenerator` | `/models/torch/seq2seq_generator.py` |\n", + "| `SeqLabeling` | 标注模型,基类`LSTM+FC+CRF` | `/models/torch/sequence_labeling.py` |\n", + "| `BiLSTMCRF` | 标注模型,`BiLSTM+FC+CRF` | `/models/torch/sequence_labeling.py` |\n", + "| `AdvSeqLabel` | 标注模型,`LN+BiLSTM*2+LN+FC+CRF` | `/models/torch/sequence_labeling.py` |" + ] + }, + { + "cell_type": "markdown", + "id": "61318354", + "metadata": {}, + "source": [ + "上述`fastNLP`模块,不仅**为入门级用户提供了简单易用的工具**,以解决各种`NLP`任务,或复现相关论文\n", + "\n", + "  同时**也为专业研究人员提供了便捷可操作的接口**,封装部分代码的同时,也能指定参数修改细节\n", + "\n", + "  在接下来的`tutorial`中,我们将通过`SST-2`分类和`CoNLL-2003`标注,展示相关模型使用\n", + "\n", + "注一:**`SST`**,**单句情感分类**数据集,包含电影评论和对应情感极性,1 对应正面情感,0 对应负面情感\n", + "\n", + "  数据集包括三部分:训练集 67350 条,验证集 873 条,测试集 1821 条,更多参考[下载链接](https://gluebenchmark.com/tasks)\n", + "\n", + "注二:**`CoNLL-2003`**,**文本语法标注**数据集,包含语句和对应的词性标签`pos_tags`(名动形数量代)\n", + "\n", + "  语法结构标签`chunk_tags`(主谓宾定状补)、命名实体标签`ner_tags`(人名、组织名、地名、时间等)\n", + "\n", + "  数据集包括三部分:训练集 14041 条,验证集 3250 条,测试集 3453 条,更多参考[原始论文](https://aclanthology.org/W03-0419.pdf)" + ] + }, + { + "cell_type": "markdown", + "id": "2a36bbe4", + "metadata": {}, + "source": [ + "### 1.2 示例一:modules 实现 LSTM 分类" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "40e66b21", + "metadata": {}, + "outputs": [], + "source": [ + "# import sys\n", + "# sys.path.append('..')\n", + "\n", + "# from fastNLP.io import SST2Pipe # 没有 SST2Pipe 会运行很长时间,并且还会报错\n", + "\n", + "# databundle = SST2Pipe(tokenizer='raw').process_from_file()\n", + "\n", + "# dataset = databundle.get_dataset('train')[:6000]\n", + "\n", + "# dataset.apply_more(lambda ins:{'words': ins['sentence'].lower().split(), 'target': ins['label']}, \n", + "# progress_bar=\"tqdm\")\n", + "# dataset.delete_field('sentence')\n", + "# dataset.delete_field('label')\n", + "# dataset.delete_field('idx')\n", + "\n", + "# from fastNLP import Vocabulary\n", + "\n", + "# vocab = Vocabulary()\n", + "# vocab.from_dataset(dataset, field_name='words')\n", + "# vocab.index_dataset(dataset, field_name='words')\n", + "\n", + "# train_dataset, evaluate_dataset = dataset.split(ratio=0.85)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "50960476", + "metadata": {}, + "outputs": [], + "source": [ + "# from fastNLP import prepare_torch_dataloader\n", + "\n", + "# train_dataloader = prepare_torch_dataloader(train_dataset, batch_size=16, shuffle=True)\n", + "# evaluate_dataloader = prepare_torch_dataloader(evaluate_dataset, batch_size=16)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0b25b25c", + "metadata": {}, + "outputs": [], + "source": [ + "# import torch\n", + "# import torch.nn as nn\n", + "\n", + "# from fastNLP.modules.torch import LSTM, MLP # 没有 MLP\n", + "# from fastNLP import Embedding, CrossEntropyLoss\n", + "\n", + "\n", + "# class ClsByModules(nn.Module):\n", + "# def __init__(self, vocab_size, embedding_dim, output_dim, hidden_dim=64, num_layers=2, dropout=0.5):\n", + "# nn.Module.__init__(self)\n", + "\n", + "# self.embedding = Embedding((vocab_size, embedding_dim))\n", + "# self.lstm = LSTM(embedding_dim, hidden_dim, num_layers=num_layers, bidirectional=True)\n", + "# self.mlp = MLP([hidden_dim * 2, output_dim], dropout=dropout)\n", + " \n", + "# self.loss_fn = CrossEntropyLoss()\n", + "\n", + "# def forward(self, words):\n", + "# output = self.embedding(words)\n", + "# output, (hidden, cell) = self.lstm(output)\n", + "# output = self.mlp(torch.cat((hidden[-1], hidden[-2]), dim=1))\n", + "# return output\n", + " \n", + "# def train_step(self, words, target):\n", + "# pred = self(words)\n", + "# return {\"loss\": self.loss_fn(pred, target)}\n", + "\n", + "# def evaluate_step(self, words, target):\n", + "# pred = self(words)\n", + "# pred = torch.max(pred, dim=-1)[1]\n", + "# return {\"pred\": pred, \"target\": target}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9dbbf50d", + "metadata": {}, + "outputs": [], + "source": [ + "# model = ClsByModules(vocab_size=len(vocabulary), embedding_dim=100, output_dim=2)\n", + "\n", + "# from torch.optim import AdamW\n", + "\n", + "# optimizers = AdamW(params=model.parameters(), lr=5e-5)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7a93432f", + "metadata": {}, + "outputs": [], + "source": [ + "# from fastNLP import Trainer, Accuracy\n", + "\n", + "# trainer = Trainer(\n", + "# model=model,\n", + "# driver='torch',\n", + "# device=0, # 'cuda'\n", + "# n_epochs=10,\n", + "# optimizers=optimizers,\n", + "# train_dataloader=train_dataloader,\n", + "# evaluate_dataloaders=evaluate_dataloader,\n", + "# metrics={'acc': Accuracy()}\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "31102e0f", + "metadata": {}, + "outputs": [], + "source": [ + "# trainer.run(num_eval_batch_per_dl=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8bc4bfb2", + "metadata": {}, + "outputs": [], + "source": [ + "# trainer.evaluator.run()" + ] + }, + { + "cell_type": "markdown", + "id": "d9443213", + "metadata": {}, + "source": [ + "## 2. fastNLP 中 models 模块的介绍\n", + "\n", + "### 2.1 示例一:models 实现 CNN 分类\n", + "\n", + "  本示例使用`fastNLP 0.8`中预定义模型`models`中的`CNNText`模型,实现`SST-2`文本二分类任务\n", + "\n", + "模型使用方面,如上所述,这里使用**基于卷积神经网络`CNN`的预定义文本分类模型`CNNText`**,结构如下所示\n", + "\n", + "  首先是内置的`100`维嵌入层、`dropout`层、紧接着是三个一维卷积,将`100`维嵌入特征,分别通过\n", + "\n", + "    **感受野为`1`、`3`、`5`的卷积算子变换至`30`维、`40`维、`50`维的卷积特征**,再将三者拼接\n", + "\n", + "  最终再次通过`dropout`层、线性变换层,映射至二元的输出值,对应两个分类结果上的几率`logits`\n", + "\n", + "```\n", + "CNNText(\n", + " (embed): Embedding(\n", + " (embed): Embedding(5194, 100)\n", + " (dropout): Dropout(p=0.0, inplace=False)\n", + " )\n", + " (conv_pool): ConvMaxpool(\n", + " (convs): ModuleList(\n", + " (0): Conv1d(100, 30, kernel_size=(1,), stride=(1,), bias=False)\n", + " (1): Conv1d(100, 40, kernel_size=(3,), stride=(1,), padding=(1,), bias=False)\n", + " (2): Conv1d(100, 50, kernel_size=(5,), stride=(1,), padding=(2,), bias=False)\n", + " )\n", + " )\n", + " (dropout): Dropout(p=0.1, inplace=False)\n", + " (fc): Linear(in_features=120, out_features=2, bias=True)\n", + ")\n", + "```\n", + "\n", + "数据使用方面,此处**使用`datasets`模块中的`load_dataset`函数**,以如下形式,指定`SST-2`数据集自动加载\n", + "\n", + "  首次下载后会保存至`~/.cache/huggingface/modules/datasets_modules/datasets/glue/`目录下" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1aa5cf6d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using the latest cached version of the module from /remote-home/xrliu/.cache/huggingface/modules/datasets_modules/datasets/glue/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad (last modified on Thu May 26 15:30:15 2022) since it couldn't be found locally at glue., or remotely on the Hugging Face Hub.\n", + "Reusing dataset glue (/remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "70cde65067c64fdba1d5e798e2b8d631", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00\n", + "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Processing: 0%| | 0/6000 [00:00[17:45:59] INFO Running evaluator sanity check for 2 batches. trainer.py:592\n", + "\n" + ], + "text/plain": [ + "\u001b[2;36m[17:45:59]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches. \u001b]8;id=147745;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=708408;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.575,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 92.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.575\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m92.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.75625,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 121.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.75625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m121.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.78125,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 125.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.78125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m125.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.8,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 128.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.8\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m128.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.79375,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 127.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.79375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m127.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.80625,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 129.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.80625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m129.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.81875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 131.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.81875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m131.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.825,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 132.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.825\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m132.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.81875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 131.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.81875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m131.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.81875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 131.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.81875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m131.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "trainer.run(num_eval_batch_per_dl=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f47a6a35", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "{'acc#acc': 0.79, 'total#acc': 900.0, 'correct#acc': 711.0}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7c811257",
+   "metadata": {},
+   "source": [
+    "  注:此处使用`gc`模块删除相关变量,释放内存,为接下来新的模型训练预留存储空间"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "c1a2e2ca",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "342"
+      ]
+     },
+     "execution_count": 15,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "import gc\n",
+    "\n",
+    "del model\n",
+    "del trainer\n",
+    "del dataset\n",
+    "del sst2data\n",
+    "\n",
+    "gc.collect()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6aec2a19",
+   "metadata": {},
+   "source": [
+    "### 2.2  示例二:models 实现 BiLSTM 标注\n",
+    "\n",
+    "  通过两个示例一的对比可以发现,得益于`models`对模型结构的封装,使用`models`明显更加便捷\n",
+    "\n",
+    "    针对更加复杂的模型时,编码更加轻松;本示例将使用`models`中的`BiLSTMCRF`模型\n",
+    "\n",
+    "  避免`CRF`和`Viterbi`算法代码书写的困难,轻松实现`CoNLL-2003`中的命名实体识别`NER`任务\n",
+    "\n",
+    "模型使用方面,如上所述,这里使用**基于双向`LSTM`+条件随机场`CRF`的标注模型`BiLSTMCRF`**,结构如下所示\n",
+    "\n",
+    "  其中,隐藏层维度默认`100`维,因此对应双向`LSTM`输出`200`维,`dropout`层退学概率、`LSTM`层数可调\n",
+    "\n",
+    "```\n",
+    "BiLSTMCRF(\n",
+    "  (embed): Embedding(7590, 100)\n",
+    "  (lstm): LSTM(\n",
+    "    (lstm): LSTM(100, 100, batch_first=True, bidirectional=True)\n",
+    "  )\n",
+    "  (dropout): Dropout(p=0.1, inplace=False)\n",
+    "  (fc): Linear(in_features=200, out_features=9, bias=True)\n",
+    "  (crf): ConditionalRandomField()\n",
+    ")\n",
+    "```\n",
+    "\n",
+    "数据使用方面,此处仍然**使用`datasets`模块中的`load_dataset`函数**,以如下形式,加载`CoNLL-2003`数据集\n",
+    "\n",
+    "  首次下载后会保存至`~.cache/huggingface/datasets/conll2003/conll2003/1.0.0/`目录下"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "03e66686",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "Reusing dataset conll2003 (/remote-home/xrliu/.cache/huggingface/datasets/conll2003/conll2003/1.0.0/63f4ebd1bcb7148b1644497336fd74643d4ce70123334431a3c053b7ee4e96ee)\n"
+     ]
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "3ec9e0ce9a054339a2453420c2c9f28b",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "  0%|          | 0/3 [00:00[17:49:16] INFO     Running evaluator sanity check for 2 batches.              trainer.py:592\n",
+       "\n"
+      ],
+      "text/plain": [
+       "\u001b[2;36m[17:49:16]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO    \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches.              \u001b]8;id=766109;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=787419;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.220374,\n",
+       "  \"pre#F1\": 0.25,\n",
+       "  \"rec#F1\": 0.197026\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.220374\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.25\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.197026\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.442857,\n",
+       "  \"pre#F1\": 0.426117,\n",
+       "  \"rec#F1\": 0.460967\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.442857\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.426117\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.460967\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.572954,\n",
+       "  \"pre#F1\": 0.549488,\n",
+       "  \"rec#F1\": 0.598513\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.572954\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.549488\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.598513\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.665399,\n",
+       "  \"pre#F1\": 0.680934,\n",
+       "  \"rec#F1\": 0.650558\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.665399\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.680934\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.650558\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.734694,\n",
+       "  \"pre#F1\": 0.733333,\n",
+       "  \"rec#F1\": 0.736059\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.734694\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.733333\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.736059\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.742647,\n",
+       "  \"pre#F1\": 0.734545,\n",
+       "  \"rec#F1\": 0.750929\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.742647\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.734545\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.750929\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.773585,\n",
+       "  \"pre#F1\": 0.785441,\n",
+       "  \"rec#F1\": 0.762082\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.773585\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.785441\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.762082\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.770115,\n",
+       "  \"pre#F1\": 0.794466,\n",
+       "  \"rec#F1\": 0.747212\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.770115\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.794466\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.747212\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.7603,\n",
+       "  \"pre#F1\": 0.766038,\n",
+       "  \"rec#F1\": 0.754647\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.7603\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.766038\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.754647\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"f#F1\": 0.743682,\n",
+       "  \"pre#F1\": 0.722807,\n",
+       "  \"rec#F1\": 0.765799\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.743682\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.722807\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.765799\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "trainer.run(num_eval_batch_per_dl=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "37871d6b", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "{'f#F1': 0.75283, 'pre#F1': 0.727438, 'rec#F1': 0.780059}"
+      ]
+     },
+     "execution_count": 22,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "08752c5a",
+   "id": "96bae094",
    "metadata": {},
    "outputs": [],
    "source": []
diff --git a/tutorials/fastnlp_tutorial_6.ipynb b/tutorials/fastnlp_tutorial_6.ipynb
index bd4b37ed..2052189e 100644
--- a/tutorials/fastnlp_tutorial_6.ipynb
+++ b/tutorials/fastnlp_tutorial_6.ipynb
@@ -5,21 +5,21 @@
    "id": "fdd7ff16",
    "metadata": {},
    "source": [
-    "# T6. trainer 和 evaluator 的深入介绍(二)\n",
+    "# T6. fastNLP 与 paddle 或 jittor 的结合\n",
     "\n",
-    "  1   fastNLP 中预定义模型 models\n",
+    "  1   fastNLP 结合 paddle 训练模型\n",
     " \n",
-    "    1.1   \n",
+    "    1.1   关于 paddle 的简单介绍\n",
     "\n",
-    "    1.2   \n",
+    "    1.2   使用 paddle 搭建并训练模型\n",
     "\n",
-    "  2   fastNLP 中预定义模型 modules\n",
-    " \n",
-    "    2.1   \n",
+    "  2   fastNLP 结合 jittor 训练模型\n",
+    "\n",
+    "    2.1   关于 jittor 的简单介绍\n",
     "\n",
-    "    2.2   \n",
+    "    2.2   使用 jittor 搭建并训练模型\n",
     "\n",
-    "  3   fastNLP 中的更多 metric 类型\n",
+    "  3   fastNLP 实现 paddle 与 pytorch 互转\n",
     "\n",
     "    3.1   \n",
     "\n",
diff --git a/tutorials/fastnlp_tutorial_e1.ipynb b/tutorials/fastnlp_tutorial_e1.ipynb
index 8897c800..b0df8fc1 100644
--- a/tutorials/fastnlp_tutorial_e1.ipynb
+++ b/tutorials/fastnlp_tutorial_e1.ipynb
@@ -13,9 +13,9 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# E1. 使用 Bert + fine-tuning 完成 SST2 分类\n",
+    "# E1. 使用 Bert + fine-tuning 完成 SST-2 分类\n",
     "\n",
-    "  1   基础介绍:`GLUE`通用语言理解评估、`SST2`文本情感二分类数据集 \n",
+    "  1   基础介绍:`GLUE`通用语言理解评估、`SST-2`文本情感二分类数据集 \n",
     "\n",
     "  2   准备工作:加载`tokenizer`、预处理`dataset`、`dataloader`使用\n",
     "\n",
@@ -63,7 +63,7 @@
     "\n",
     "import fastNLP\n",
     "from fastNLP import Trainer\n",
-    "from fastNLP.core.metrics import Accuracy\n",
+    "from fastNLP import Accuracy\n",
     "\n",
     "print(transformers.__version__)"
    ]
@@ -72,11 +72,11 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "### 1. 基础介绍:GLUE 通用语言理解评估、SST2 文本情感二分类数据集\n",
+    "### 1. 基础介绍:GLUE 通用语言理解评估、SST-2 文本情感二分类数据集\n",
     "\n",
-    "  本示例使用`GLUE`评估基准中的`SST2`数据集,通过`fine-tuning`方式\n",
+    "  本示例使用`GLUE`评估基准中的`SST-2`数据集,通过`fine-tuning`方式\n",
     "\n",
-    "    调整`distilbert-bert`分类模型,以下首先简单介绍下`GLUE`和`SST2`\n",
+    "    调整`distilbert-bert`分类模型,以下首先简单介绍下`GLUE`和`SST-2`\n",
     "\n",
     "**`GLUE`**,**全称`General Language Understanding Evaluation`**,**通用语言理解评估**,\n",
     "\n",
@@ -92,7 +92,7 @@
     "\n",
     "  诸如`BERT`、`T5`等经典模型都会在此基准上验证效果,更多参考[GLUE论文](https://arxiv.org/pdf/1804.07461v3.pdf)\n",
     "\n",
-    "    此处,我们使用`SST2`来训练`bert`,实现文本分类,其他任务描述见下图"
+    "    此处,我们使用`SST-2`来训练`bert`,实现文本分类,其他任务描述见下图"
    ]
   },
   {
@@ -116,9 +116,9 @@
     "\n",
     "  包含电影评论语句和对应的情感极性,1 对应`positive` 正面情感,0 对应`negative` 负面情感\n",
     "\n",
-    "  数据集包括三部分:训练集 67350 条,开发集 873 条,测试集 1821 条,更多参考[下载链接](https://gluebenchmark.com/tasks)\n",
+    "  数据集包括三部分:训练集 67350 条,验证集 873 条,测试集 1821 条,更多参考[下载链接](https://gluebenchmark.com/tasks)\n",
     "\n",
-    "对应到代码上,此处使用`datasets`模块中的`load_dataset`函数,指定`SST2`数据集,自动加载\n",
+    "对应到代码上,此处使用`datasets`模块中的`load_dataset`函数,指定`SST-2`数据集,自动加载\n",
     "\n",
     "  首次下载后会保存至`~/.cache/huggingface/modules/datasets_modules/datasets/glue/`目录下"
    ]
@@ -134,14 +134,13 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "Using the latest cached version of the module from /remote-home/xrliu/.cache/huggingface/modules/datasets_modules/datasets/glue/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad (last modified on Thu May 26 15:30:15 2022) since it couldn't be found locally at glue., or remotely on the Hugging Face Hub.\n",
       "Reusing dataset glue (/remote-home/xrliu/.cache/huggingface/datasets/glue/sst2/1.0.0/dacbe3125aa31d7f70367a07a8a9e72a5a0bfeb5fc42e75c9db75b96da6053ad)\n"
      ]
     },
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "adc9449171454f658285f220b70126e1",
+       "model_id": "c5915debacf9443986b5b3b34870b303",
        "version_major": 2,
        "version_minor": 0
       },
@@ -163,7 +162,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "  加载之后,根据`GLUE`中`SST2`数据集的格式,尝试打印部分数据,检查加载结果"
+    "  加载之后,根据`GLUE`中`SST-2`数据集的格式,尝试打印部分数据,检查加载结果"
    ]
   },
   {
@@ -287,7 +286,7 @@
     "\n",
     "  其中,**`__getitem__`函数各返回值引用的键值**,**必须和原始数据集中的属性对应**\n",
     "\n",
-    "  例如,`'label'`是`SST2`数据集中原有的内容(包括`'sentence'`和`'label'`\n",
+    "  例如,`'label'`是`SST-2`数据集中原有的内容(包括`'sentence'`和`'label'`\n",
     "\n",
     "    `'input_ids'`和`'attention_mask'`则是`tokenizer`处理后添加的字段"
    ]
@@ -440,10 +439,10 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForSequenceClassification: ['vocab_layer_norm.weight', 'vocab_layer_norm.bias', 'vocab_projector.weight', 'vocab_transform.bias', 'vocab_projector.bias', 'vocab_transform.weight']\n",
+      "Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForSequenceClassification: ['vocab_transform.bias', 'vocab_projector.bias', 'vocab_layer_norm.weight', 'vocab_projector.weight', 'vocab_transform.weight', 'vocab_layer_norm.bias']\n",
       "- This IS expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
       "- This IS NOT expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
-      "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['pre_classifier.bias', 'classifier.weight', 'classifier.bias', 'pre_classifier.weight']\n",
+      "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.weight', 'pre_classifier.weight', 'classifier.bias', 'pre_classifier.bias']\n",
       "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
      ]
     }
@@ -472,7 +471,7 @@
     "trainer = Trainer(\n",
     "    model=model,\n",
     "    driver='torch',\n",
-    "    device=1,  # 'cuda'\n",
+    "    device=0,  # 'cuda'\n",
     "    n_epochs=10,\n",
     "    optimizers=optimizers,\n",
     "    train_dataloader=dataloader_train,\n",
@@ -495,6 +494,33 @@
    "execution_count": 13,
    "metadata": {},
    "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
[09:12:45] INFO     Running evaluator sanity check for 2 batches.              trainer.py:592\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[09:12:45]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running evaluator sanity check for \u001b[1;36m2\u001b[0m batches. \u001b]8;id=408427;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=303634;file://../fastNLP/core/controllers/trainer.py#592\u001b\\\u001b[2m592\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -505,6 +531,490 @@ "metadata": {}, "output_type": "display_data" }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:1, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.884375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 283.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.884375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m283.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:2, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m2\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.878125,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 281.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.878125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m281.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:3, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m3\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.884375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 283.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.884375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m283.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:4, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m4\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.9,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 288.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.9\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m288.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:5, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m5\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.8875,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 284.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.8875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m284.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:6, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m6\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.88125,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 282.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.88125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m282.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:7, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m7\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.875,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 280.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m280.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:8, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m8\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.865625,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 277.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.865625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m277.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
----------------------------- Eval. results on Epoch:9, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "----------------------------- Eval. results on Epoch:\u001b[1;36m9\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.884375,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 283.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.884375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m283.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:10, Batch:0 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m10\u001b[0m, Batch:\u001b[1;36m0\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#acc\": 0.878125,\n",
+       "  \"total#acc\": 320.0,\n",
+       "  \"correct#acc\": 281.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.878125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m320.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m281.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -540,10 +1050,14 @@ "outputs": [ { "data": { - "text/html": [ - "
\n"
-      ],
-      "text/plain": []
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "Output()"
+      ]
      },
      "metadata": {},
      "output_type": "display_data"
@@ -561,7 +1075,7 @@
     {
      "data": {
       "text/plain": [
-       "{'acc#acc': 0.87156, 'total#acc': 872.0, 'correct#acc': 760.0}"
+       "{'acc#acc': 0.884174, 'total#acc': 872.0, 'correct#acc': 771.0}"
       ]
      },
      "execution_count": 14,
diff --git a/tutorials/fastnlp_tutorial_e2.ipynb b/tutorials/fastnlp_tutorial_e2.ipynb
index c8f4b7dc..ca0b4754 100644
--- a/tutorials/fastnlp_tutorial_e2.ipynb
+++ b/tutorials/fastnlp_tutorial_e2.ipynb
@@ -4,7 +4,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# E2. 使用 Bert + prompt 完成 SST2 分类\n",
+    "# E2. 使用 Bert + prompt 完成 SST-2 分类\n",
     "\n",
     "  1   基础介绍:`prompt-based model`简介、与`fastNLP`的结合\n",
     "\n",
@@ -19,7 +19,7 @@
    "source": [
     "### 1. 基础介绍:prompt-based model 简介、与 fastNLP 的结合\n",
     "\n",
-    "  本示例使用`GLUE`评估基准中的`SST2`数据集,通过`prompt-based tuning`方式\n",
+    "  本示例使用`GLUE`评估基准中的`SST-2`数据集,通过`prompt-based tuning`方式\n",
     "\n",
     "    微调`bert-base-uncased`模型,实现文本情感的二分类,在此之前本示例\n",
     "\n",
@@ -27,41 +27,53 @@
     "\n",
     "**`prompt`**,**提示词**,最早出自论文[Exploiting Cloze Questions for Few Shot TC and NLI](https://arxiv.org/pdf/2001.07676.pdf)中的**`PET`模型**\n",
     "\n",
-    "    全称 **`Pattern-Exploiting Training`**,虽然文中并没有提到**`prompt`的说法,但仍视为其开山之作\n",
+    "    全称 **`Pattern-Exploiting Training`**,虽然文中并没有提到`prompt`的说法,但仍被视为开山之作\n",
     "\n",
-    "  其大致思路包括,对于文本分类任务,假定输入文本为,后来被称`prompt`,后来被称`verbalizer`,\n",
+    "  其大致思路包括,对于文本分类任务,假定输入文本为`\" X . \"`,设计**输入模板`template`**,**后来被称为`prompt`**\n",
     "\n",
-    "  其主要贡献在于,\n",
+    "    将输入重构为`\" X . It is [MASK] . \"`,**诱导或刺激语言模型在`[MASK]`位置生成含有情感倾向的词汇**\n",
+    "\n",
+    "    接着将该词汇**输入分类器中**,**后来被称为`verbalizer`**,从而得到该语句对应的情感倾向,实现文本分类\n",
+    "\n",
+    "  其主要贡献在于,通过构造`prompt`,诱导/刺激预训练模型生成期望适应下游任务特征,适合少样本学习的需求\n",
     "\n",
     "\n",
     "\n",
-    "**`prompt-based tuning`**,**基于提示的微调**,\n",
+    "**`prompt-based tuning`**,**基于提示的微调**,将`prompt`应用于**参数高效微调**,**`parameter-efficient tuning`**\n",
+    "\n",
+    "  通过**设计模板调整模型输入**或者**调整模型内部状态**,**固定预训练模型**,**诱导/刺激模型**调整输出以适应\n",
     "\n",
-    "  xxxx,更多参考[prompt综述](https://arxiv.org/pdf/2107.13586.pdf)\n",
+    "  当前任务,极大降低了训练开销,也省去了`verbalizer`的构造,更多参考[prompt综述](https://arxiv.org/pdf/2107.13586.pdf)、[DeltaTuning综述](https://arxiv.org/pdf/2203.06904.pdf)\n",
     "\n",
     "    以下列举些经典的`prompt-based tuning`案例,简单地介绍下`prompt-based tuning`的脉络\n",
     "\n",
-    "  案例一:**`P-Tuning v1`**,详细内容参考[P-Tuning-v1论文](https://arxiv.org/pdf/2103.10385.pdf)\n",
+    "  **案例一**:**`PrefixTuning`**,详细内容参考[PrefixTuning论文](https://arxiv.org/pdf/2101.00190.pdf)\n",
+    "\n",
+    "    其主要贡献在于,**提出连续的、非人工构造的、任务导向的`prompt`**,即**前缀`prefix`**,**调整**\n",
+    "\n",
+    "      **模型内部更新状态**,诱导模型在特定任务下生成期望目标,降低优化难度,提升微调效果\n",
+    "\n",
+    "    其主要研究对象,是`GPT2`和`BART`,主要面向生成任务`NLG`,如`table-to-text`和摘要\n",
     "\n",
-    "    其主要贡献在于,\n",
+    "  **案例二**:**`P-Tuning v1`**,详细内容参考[P-Tuning-v1论文](https://arxiv.org/pdf/2103.10385.pdf)\n",
     "\n",
-    "    其方法大致包括,\n",
+    "    其主要贡献在于,**通过连续的、非人工构造的`prompt`调整模型输入**,取代原先基于单词设计的\n",
     "\n",
-    "  案例二:**`PromptTuning`**,详细内容参考[PromptTuning论文](https://arxiv.org/pdf/2104.08691.pdf)\n",
+    "      但离散且不易于优化的`prompt`;同时也**证明了`GPT2`在语言理解任务上仍然是可以胜任的**\n",
     "\n",
-    "    其主要贡献在于,\n",
+    "    其主要研究对象,是`GPT2`,主要面向知识探测`knowledge probing`和自然语言理解`NLU`\n",
     "\n",
-    "    其方法大致包括,\n",
+    "  **案例三**:**`PromptTuning`**,详细内容参考[PromptTuning论文](https://arxiv.org/pdf/2104.08691.pdf)\n",
     "\n",
-    "  案例三:**`PrefixTuning`**,详细内容参考[PrefixTuning论文](https://arxiv.org/pdf/2101.00190.pdf)\n",
+    "    其主要贡献在于,通过连续的`prompt`调整模型输入,**证明了`prompt-based tuning`的效果**\n",
     "\n",
-    "    其主要贡献在于,\n",
+    "      **随模型参数量的增加而提升**,最终**在`10B`左右追上了全参数微调`fine-tuning`的效果**\n",
     "\n",
-    "    其方法大致包括,\n",
+    "    其主要面向自然语言理解`NLU`,通过为每个任务定义不同的`prompt`,从而支持多任务语境\n",
     "\n",
     "通过上述介绍可以发现`prompt-based tuning`只是模型微调方式,独立于预训练模型基础`backbone`\n",
     "\n",
-    "  目前,加载预训练模型的主流方法是使用`transformers`模块,而实现微调的框架则\n",
+    "  目前,加载预训练模型的主流方法是使用**`transformers`模块**,而实现微调的框架则\n",
     "\n",
     "    可以是`pytorch`、`paddle`、`jittor`等,而不同框架间又存在不兼容的问题\n",
     "\n",
@@ -69,9 +81,9 @@
     "\n",
     "    **和`transformers`模块之间的桥接**(`transformers`模块基于`pytorch`实现)\n",
     "\n",
-    "本示例仍使用了`tutorial-E1`的`SST2`数据集、`distilbert-base-uncased`模型(便于比较\n",
+    "本示例仍使用了`tutorial-E1`的`SST-2`数据集、`distilbert-base-uncased`模型(便于比较\n",
     "\n",
-    "  使用`pytorch`框架,通过将连续的`prompt`与`model`拼接,解决`SST2`二分类任务"
+    "  使用`pytorch`框架,通过将连续的`prompt`与`model`拼接,解决`SST-2`二分类任务"
    ]
   },
   {
@@ -246,7 +258,7 @@
    "source": [
     "### 3. 模型训练:加载 tokenizer、预处理 dataset、模型训练与分析\n",
     "\n",
-    "  本示例沿用`tutorial-E1`中的数据集,即使用`GLUE`评估基准中的`SST2`数据集\n",
+    "  本示例沿用`tutorial-E1`中的数据集,即使用`GLUE`评估基准中的`SST-2`数据集\n",
     "\n",
     "    以`bert-base-uncased`模型作为基准,基于`P-Tuning v2`方式微调\n",
     "\n",