From 46f9cab9974a321383e4319d1bfdcb8a80bf019a Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:20:30 +0000 Subject: [PATCH 01/14] =?UTF-8?q?fastNLP/io=20=E9=83=A8=E5=88=86=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastNLP/io/__init__.py | 6 +- fastNLP/io/data_bundle.py | 235 ++++++------- fastNLP/io/embed_loader.py | 60 ++-- fastNLP/io/file_reader.py | 4 - fastNLP/io/file_utils.py | 51 +-- fastNLP/io/loader/__init__.py | 13 +- fastNLP/io/loader/classification.py | 250 ++++++------- fastNLP/io/loader/conll.py | 140 ++++---- fastNLP/io/loader/csv.py | 20 +- fastNLP/io/loader/cws.py | 25 +- fastNLP/io/loader/json.py | 19 +- fastNLP/io/loader/loader.py | 37 +- fastNLP/io/loader/matching.py | 151 ++++---- fastNLP/io/loader/qa.py | 24 +- fastNLP/io/loader/summarization.py | 64 ++++ fastNLP/io/pipe/classification.py | 463 ++++++++++--------------- fastNLP/io/pipe/conll.py | 200 +++++------ fastNLP/io/pipe/construct_graph.py | 80 ++++- fastNLP/io/pipe/cws.py | 7 +- fastNLP/io/pipe/matching.py | 112 ++++++ fastNLP/io/pipe/pipe.py | 8 +- fastNLP/io/pipe/qa.py | 8 +- fastNLP/io/pipe/summarization.py | 8 +- fastNLP/io/pipe/utils.py | 2 +- fastNLP/io/utils.py | 16 +- fastNLP/transformers/__init__.py | 5 +- fastNLP/transformers/torch/__init__.py | 14 +- 27 files changed, 1064 insertions(+), 958 deletions(-) create mode 100644 fastNLP/io/loader/summarization.py diff --git a/fastNLP/io/__init__.py b/fastNLP/io/__init__.py index 3897cb0d..e525fee2 100644 --- a/fastNLP/io/__init__.py +++ b/fastNLP/io/__init__.py @@ -1,13 +1,13 @@ r""" -用于IO的模块, 具体包括: +用于 **IO** 的模块, 具体包括: -1. 用于读入 embedding 的 :mod:`EmbedLoader ` 类, +1. 用于读入 embedding 的 :mod:`EmbedLoader ` 类 2. 用于读入不同格式数据的 :mod:`Loader ` 类 3. 用于处理读入数据的 :mod:`Pipe ` 类 -4. 用于保存和载入模型的类, 参考 :mod:`model_io模块 ` +4. 用于管理数据集的类 :mod:`DataBundle ` 类 这些类的使用方法如下: """ diff --git a/fastNLP/io/data_bundle.py b/fastNLP/io/data_bundle.py index 4029e092..69e092cc 100644 --- a/fastNLP/io/data_bundle.py +++ b/fastNLP/io/data_bundle.py @@ -1,7 +1,7 @@ -r""" -.. todo:: - doc """ +:class:`DataBundle` 是 **fastNLP** 提供的用于方便快捷地管理多个数据集的工具,并有诸多接口来进行批量的数据处理。 +""" + __all__ = [ 'DataBundle', ] @@ -15,45 +15,40 @@ from fastNLP.core import logger class DataBundle: r""" - 经过处理的数据信息,包括一系列数据集(比如:分开的训练集、验证集和测试集)以及各个field对应的vocabulary。该对象一般由fastNLP中各种 - Loader的load函数生成,可以通过以下的方法获取里面的内容 - - Example:: + 经过处理的数据信息,包括一系列数据集(比如:分开的训练集、验证集和测试集)以及各个 field 对应的 vocabulary。该对象一般由 + **fastNLP** 中各种 :class:`~fastNLP.io.loader.Loader` 的 :meth:`load` 函数生成,可以通过以下的方法获取里面的内容:: data_bundle = YelpLoader().load({'train':'/path/to/train', 'dev': '/path/to/dev'}) train_vocabs = data_bundle.vocabs['train'] train_data = data_bundle.datasets['train'] dev_data = data_bundle.datasets['train'] + :param vocabs: 从名称(字符串)到 :class:`~fastNLP.core.Vocabulary` 类型的字典 + :param datasets: 从名称(字符串)到 :class:`~fastNLP.core.dataset.DataSet` 类型的字典。建议不要将相同的 ``DataSet`` 对象重复传入, + 否则可能会在使用 :class:`~fastNLP.io.pipe.Pipe` 处理数据的时候遇到问题,若多个数据集确需一致,请手动 ``deepcopy`` 后传入。 """ def __init__(self, vocabs=None, datasets=None): - r""" - - :param vocabs: 从名称(字符串)到 :class:`~fastNLP.Vocabulary` 类型的dict - :param datasets: 从名称(字符串)到 :class:`~fastNLP.DataSet` 类型的dict。建议不要将相同的DataSet对象重复传入,可能会在 - 使用Pipe处理数据的时候遇到问题,若多个数据集确需一致,请手动deepcopy后传入。 - """ self.vocabs = vocabs or {} self.datasets = datasets or {} def set_vocab(self, vocab: Vocabulary, field_name: str): r""" - 向DataBunlde中增加vocab + 向 :class:`DataBunlde` 中增加 ``vocab`` - :param ~fastNLP.Vocabulary vocab: 词表 - :param str field_name: 这个vocab对应的field名称 + :param vocab: :class:`~fastNLP.core.Vocabulary` 类型的词表 + :param field_name: 这个 vocab 对应的 field 名称 :return: self """ - assert isinstance(vocab, Vocabulary), "Only fastNLP.Vocabulary supports." + assert isinstance(vocab, Vocabulary), "Only fastNLP.core.Vocabulary supports." self.vocabs[field_name] = vocab return self def set_dataset(self, dataset: DataSet, name: str): r""" - :param ~fastNLP.DataSet dataset: 传递给DataBundle的DataSet - :param str name: dataset的名称 + :param dataset: 传递给 :class:`DataBundle` 的 :class:`~fastNLP.core.dataset.DataSet` + :param name: ``dataset`` 的名称 :return: self """ assert isinstance(dataset, DataSet), "Only fastNLP.DataSet supports." @@ -62,10 +57,10 @@ class DataBundle: def get_dataset(self, name: str) -> DataSet: r""" - 获取名为name的dataset + 获取名为 ``name`` 的 dataset - :param str name: dataset的名称,一般为'train', 'dev', 'test' - :return: DataSet + :param name: dataset的名称,一般为 'train', 'dev', 'test' 。 + :return: """ if name in self.datasets.keys(): return self.datasets[name] @@ -77,33 +72,34 @@ class DataBundle: def delete_dataset(self, name: str): r""" - 删除名为name的DataSet + 删除名为 ``name`` 的 dataset - :param str name: + :param name: :return: self """ self.datasets.pop(name, None) return self - def get_vocab(self, field_name: str) -> Vocabulary: + def get_vocab(self, name: str) -> Vocabulary: r""" - 获取field名为field_name对应的vocab + 获取 field 名为 ``field_name`` 对应的词表 - :param str field_name: 名称 - :return: Vocabulary + :param field_name: 名称 + :return: :class:`~fastNLP.core.Vocabulary` """ - if field_name in self.vocabs.keys(): - return self.vocabs[field_name] + if name in self.vocabs.keys(): + return self.vocabs[name] else: - error_msg = f'DataBundle do NOT have Vocabulary named {field_name}. ' \ + error_msg = f'DataBundle do NOT have Vocabulary named {name}. ' \ f'It should be one of {self.vocabs.keys()}.' logger.error(error_msg) raise KeyError(error_msg) def delete_vocab(self, field_name: str): r""" - 删除vocab - :param str field_name: + 删除名为 ``field_name`` 的 vocab + + :param field_name: :return: self """ self.vocabs.pop(field_name, None) @@ -117,14 +113,14 @@ class DataBundle: def num_vocab(self): return len(self.vocabs) - def copy_field(self, field_name: str, new_field_name: str, ignore_miss_dataset=True): + def copy_field(self, field_name: str, new_field_name: str, ignore_miss_dataset: bool=True): r""" - 将DataBundle中所有的DataSet中名为field_name的Field复制一份并命名为叫new_field_name. + 将所有的 dataset 中名为 ``field_name`` 的 Field 复制一份并命名为 ``new_field_name``。 - :param str field_name: - :param str new_field_name: - :param bool ignore_miss_dataset: 当某个field名称在某个dataset不存在时,如果为True,则直接忽略该DataSet; - 如果为False,则报错 + :param field_name: + :param new_field_name: + :param ignore_miss_dataset: 如果为 ``True`` ,则当 ``field_name`` 在某个 dataset 内不存在时,直接忽略该 dataset, + 如果为 ``False`` 则会报错。 :return: self """ for name, dataset in self.datasets.items(): @@ -134,15 +130,15 @@ class DataBundle: raise KeyError(f"{field_name} not found DataSet:{name}.") return self - def rename_field(self, field_name: str, new_field_name: str, ignore_miss_dataset=True, rename_vocab=True): + def rename_field(self, field_name: str, new_field_name: str, ignore_miss_dataset: bool=True, rename_vocab: bool=True): r""" - 将DataBundle中所有DataSet中名为field_name的field重命名为new_field_name. + 将所有的 dataset 中名为 ``field_name`` 的 Field 重命名为 ``new_field_name``。 - :param str field_name: - :param str new_field_name: - :param bool ignore_miss_dataset: 当某个field名称在某个dataset不存在时,如果为True,则直接忽略该DataSet; - 如果为False,则报错 - :param bool rename_vocab: 如果该field同时也存在于vocabs中,会将该field的名称对应修改 + :param field_name: + :param new_field_name: + :param ignore_miss_dataset: 如果为 ``True`` ,则当 ``field_name`` 在某个 dataset 内不存在时,直接忽略该 dataset, + 如果为 ``False`` 则会报错。 + :param rename_vocab: 如果该 ``field_name`` 同时也存在于 vocabs 中,则也会进行重命名 :return: self """ for name, dataset in self.datasets.items(): @@ -156,14 +152,14 @@ class DataBundle: return self - def delete_field(self, field_name: str, ignore_miss_dataset=True, delete_vocab=True): + def delete_field(self, field_name: str, ignore_miss_dataset: bool=True, delete_vocab: bool=True): r""" - 将DataBundle中所有DataSet中名为field_name的field删除掉. + 将所有的 dataset 中名为 ``field_name`` 的 Field 删除。 - :param str field_name: - :param bool ignore_miss_dataset: 当某个field名称在某个dataset不存在时,如果为True,则直接忽略该DataSet; - 如果为False,则报错 - :param bool delete_vocab: 如果该field也在vocabs中存在,将该值也一并删除 + :param field_name: + :param ignore_miss_dataset: 如果为 ``True`` ,则当 ``field_name`` 在某个 dataset 内不存在时,直接忽略该 dataset, + 如果为 ``False`` 则会报错。 + :param delete_vocab: 如果该 ``field_name`` 也在 vocabs 中存在,则也会删除。 :return: self """ for name, dataset in self.datasets.items(): @@ -178,44 +174,38 @@ class DataBundle: def iter_datasets(self) -> Union[str, DataSet]: r""" - 迭代data_bundle中的DataSet + 迭代 dataset Example:: for name, dataset in data_bundle.iter_datasets(): pass - :return: """ for name, dataset in self.datasets.items(): yield name, dataset def get_dataset_names(self) -> List[str]: r""" - 返回DataBundle中DataSet的名称 - - :return: + :return: 所有 dataset 的名称 """ return list(self.datasets.keys()) def get_vocab_names(self) -> List[str]: r""" - 返回DataBundle中Vocabulary的名称 - - :return: + :return: 所有词表的名称 """ return list(self.vocabs.keys()) def iter_vocabs(self): r""" - 迭代data_bundle中的DataSet + 迭代词表 - Example: + Example:: for field_name, vocab in data_bundle.iter_vocabs(): pass - :return: """ for field_name, vocab in self.vocabs.items(): yield field_name, vocab @@ -223,25 +213,24 @@ class DataBundle: def apply_field(self, func: Callable, field_name: str, new_field_name: str, num_proc: int = 0, ignore_miss_dataset: bool = True, progress_desc: str = '', progress_bar: str = 'rich'): r""" - 对 :class:`~fastNLP.io.DataBundle` 中所有的dataset使用 :meth:`~fastNLP.DataSet.apply_field` 方法 - - :param callable func: input是instance中名为 `field_name` 的field的内容。 - :param str field_name: 传入func的是哪个field。 - :param str new_field_name: 将func返回的内容放入到 `new_field_name` 这个field中,如果名称与已有的field相同,则覆 - 盖之前的field。如果为None则不创建新的field。 - :param bool ignore_miss_dataset: 当某个field名称在某个dataset不存在时,如果为True,则直接忽略该DataSet; - 如果为False,则报错 - :param num_proc: 使用进程的数量。 + 对 :class:`DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.core.dataset.DataSet.apply_field` 方法 + :param func: 对指定 field 进行处理的函数,注意其输入应为 ``instance`` 中名为 ``field_name`` 的 field 的内容; + :param field_name: 传入 ``func`` 的 field 名称; + :param new_field_name: 函数执行结果写入的 ``field`` 名称。该函数会将 ``func`` 返回的内容放入到 ``new_field_name`` 对 + 应的 ``field`` 中,注意如果名称与已有的 field 相同则会进行覆盖。如果为 ``None`` 则不会覆盖和创建 field ; + :param num_proc: 使用进程的数量。 + .. note:: - + 由于 ``python`` 语言的特性,设置该参数后会导致相应倍数的内存增长,这可能会对您程序的执行带来一定的影响。另外,使用多进程时, ``func`` 函数中的打印将不会输出。 - :param ignore_miss_dataset: 如果 dataset 没有 {field_name} ,就直接跳过这个 dataset 。 - :param progress_desc: 当显示 progress 时,可以显示当前正在处理的名称 - :param progress_bar: 显示 progress_bar 的方式,支持 `["rich", "tqdm", None]`。 - + :param ignore_miss_dataset: 如果为 ``True`` ,则当 ``field_name`` 在某个 dataset 内不存在时,直接忽略该 dataset, + 如果为 ``False`` 则会报错。 + :param progress_desc: 如果不为 ``None``,则会显示当前正在处理的进度条的名称; + :param progress_bar: 显示进度条的方式,支持 ``["rich", "tqdm", None]``。 + :return: self """ _progress_desc = progress_desc for name, dataset in self.datasets.items(): @@ -255,32 +244,30 @@ class DataBundle: raise KeyError(f"{field_name} not found DataSet:{name}.") return self - def apply_field_more(self, func: Callable, field_name: str, num_proc: int = 0, modify_fields=True, + def apply_field_more(self, func: Callable, field_name: str, modify_fields: str=True, num_proc: int = 0, ignore_miss_dataset=True, progress_bar: str = 'rich', progress_desc: str = ''): r""" - 对 :class:`~fastNLP.io.DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.DataSet.apply_field_more` 方法 + 对 :class:`DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.core.DataSet.apply_field_more` 方法 .. note:: ``apply_field_more`` 与 ``apply_field`` 的区别参考 :meth:`fastNLP.DataSet.apply_more` 中关于 ``apply_more`` 与 ``apply`` 区别的介绍。 - :param callable func: 参数是 ``DataSet`` 中的 ``Instance`` ,返回值是一个字典,key 是field 的名字,value 是对应的结果 - :param str field_name: 传入func的是哪个field。 - :param bool modify_fields: 是否用结果修改 `DataSet` 中的 `Field`, 默认为 True + :param func: 对指定 field 进行处理的函数,注意其输入应为 ``instance`` 中名为 ``field_name`` 的 field 的内容; + :param field_name: 传入 ``func`` 的 field 名称; + :param modify_fields: 是否用结果修改 ``DataSet`` 中的 ``Field`` , 默认为 ``True`` :param num_proc: 使用进程的数量。 - + .. note:: - + 由于 ``python`` 语言的特性,设置该参数后会导致相应倍数的内存增长,这可能会对您程序的执行带来一定的影响。另外,使用多进程时, ``func`` 函数中的打印将不会输出。 - :param bool ignore_miss_dataset: 当某个field名称在某个dataset不存在时,如果为True,则直接忽略该DataSet; - 如果为False,则报错 - :param progress_bar: 显示 progress_bar 的方式,支持 `["rich", "tqdm", None]`。 - :param progress_desc: 当显示 progress_bar 时,可以显示 ``progress`` 的名称。 - - :return Dict[str:Dict[str:Field]]: 返回一个字典套字典,第一层的 key 是 dataset 的名字,第二层的 key 是 field 的名字 - + :param ignore_miss_dataset: 如果为 ``True`` ,则当 ``field_name`` 在某个 dataset 内不存在时,直接忽略该 dataset, + 如果为 ``False`` 则会报错。 + :param progress_desc: 如果不为 ``None``,则会显示当前正在处理的进度条的名称; + :param progress_bar: 显示进度条的方式,支持 ``["rich", "tqdm", None]``。 + :return: 一个字典套字典,第一层的 key 是 dataset 的名字,第二层的 key 是 field 的名字 """ res = {} _progress_desc = progress_desc @@ -299,13 +286,11 @@ class DataBundle: def apply(self, func: Callable, new_field_name: str, num_proc: int = 0, progress_desc: str = '', progress_bar: bool = True): r""" - 对 :class:`~fastNLP.io.DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.DataSet.apply` 方法 - - 对DataBundle中所有的dataset使用apply方法 + 对 :class:`~DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.core.DataSet.apply` 方法 - :param callable func: input是instance中名为 `field_name` 的field的内容。 - :param str new_field_name: 将func返回的内容放入到 `new_field_name` 这个field中,如果名称与已有的field相同,则覆 - 盖之前的field。如果为None则不创建新的field。 + :param func: 参数是 ``DataSet`` 中的 ``Instance`` ,返回值是一个字典,key 是field 的名字,value 是对应的结果 + :param new_field_name: 将 ``func`` 返回的内容放入到 ``new_field_name`` 这个 field中 ,如果名称与已有的 field 相同,则覆 + 盖之前的 field。如果为 ``None`` 则不创建新的 field。 :param num_proc: 使用进程的数量。 .. note:: @@ -313,9 +298,9 @@ class DataBundle: 由于 ``python`` 语言的特性,设置该参数后会导致相应倍数的内存增长,这可能会对您程序的执行带来一定的影响。另外,使用多进程时, ``func`` 函数中的打印将不会输出。 - :param progress_bar: 显示 progress_bar 的方式,支持 `["rich", "tqdm", None]`。 - :param progress_desc: 当显示 progress bar 时,可以显示当前正在处理的名称 - + :param progress_bar: 显示进度条的方式,支持 ``["rich", "tqdm", None]``。 + :param progress_desc: 如果不为 ``None``,则会显示当前正在处理的进度条的名称。 + :return: self """ _progress_desc = progress_desc for name, dataset in self.datasets.items(): @@ -326,7 +311,7 @@ class DataBundle: progress_desc=progress_desc) return self - def apply_more(self, func: Callable, modify_fields=True, num_proc: int = 0, + def apply_more(self, func: Callable, modify_fields: bool=True, num_proc: int = 0, progress_desc: str = '', progress_bar: str = 'rich'): r""" 对 :class:`~fastNLP.io.DataBundle` 中所有的 dataset 使用 :meth:`~fastNLP.DataSet.apply_more` 方法 @@ -335,8 +320,8 @@ class DataBundle: ``apply_more`` 与 ``apply`` 的区别参考 :meth:`fastNLP.DataSet.apply_more` 中关于 ``apply_more`` 与 ``apply`` 区别的介绍。 - :param callable func: 参数是 ``DataSet`` 中的 ``Instance`` ,返回值是一个字典,key 是field 的名字,value 是对应的结果 - :param bool modify_fields: 是否用结果修改 ``DataSet`` 中的 ``Field`` , 默认为 True + :param func: 参数是 ``DataSet`` 中的 ``Instance`` ,返回值是一个字典,key 是field 的名字,value 是对应的结果 + :param modify_fields: 是否用结果修改 ``DataSet`` 中的 ``Field`` , 默认为 ``True`` :param num_proc: 使用进程的数量。 .. note:: @@ -344,10 +329,10 @@ class DataBundle: 由于 ``python`` 语言的特性,设置该参数后会导致相应倍数的内存增长,这可能会对您程序的执行带来一定的影响。另外,使用多进程时, ``func`` 函数中的打印将不会输出。 - :param progress_bar: 显示 progress_bar 的方式,支持 `["rich", "tqdm", None]`。 - :param progress_desc: 当显示 progress_bar 时,可以显示当前正在处理的名称 + :param progress_desc: 当 progress_bar 不为 ``None`` 时,可以显示当前正在处理的进度条名称 + :param progress_bar: 显示进度条的方式,支持 ``["rich", "tqdm", None]``。 - :return Dict[str:Dict[str:Field]]: 返回一个字典套字典,第一层的 key 是 dataset 的名字,第二层的 key 是 field 的名字 + :return: 一个字典套字典,第一层的 key 是 dataset 的名字,第二层的 key 是 field 的名字 """ res = {} _progress_desc = progress_desc @@ -363,19 +348,19 @@ class DataBundle: """ 如果需要对某个 field 的内容进行特殊的调整,请使用这个函数。 - :param field_name: 需要调整的 field 的名称。如果 Dataset 的 __getitem__ 方法返回的是 dict 类型的,则可以直接使用对应的 - field 的 key 来表示,如果是 nested 的 dict,可以使用元组表示多层次的 key,例如 {'a': {'b': 1}} 中的使用 ('a', 'b'); - 如果 __getitem__ 返回的是 Sequence 类型的,则可以使用 '_0', '_1' 表示序列中第 0 或 1 个元素。如果该 field 在数据中没 - 有找到,则报错;如果 __getitem__ 返回的是就是整体内容,请使用 "_single" 。 - :param pad_val: 这个 field 的默认 pad 值。如果设置为 None,则表示该 field 不需要 pad , fastNLP 默认只会对可以 pad 的 - field 进行 pad,所以如果对应 field 本身就不是可以 pad 的形式,可以不需要主动设置为 None 。如果 backend 为 None ,该值 - 无意义。 - :param dtype: 对于需要 pad 的 field ,该 field 的数据 dtype 应该是什么。 - :param backend: 可选['raw', 'numpy', 'torch', 'paddle', 'jittor', 'auto'],分别代表,输出为 list, numpy.ndarray, - torch.Tensor, paddle.Tensor, jittor.Var 类型。若 pad_val 为 None ,该值无意义 。 - :param pad_fn: 指定当前 field 的 pad 函数,传入该函数则 pad_val, dtype, backend 等参数失效。pad_fn 的输入为当前 field 的 - batch 形式。 Collator 将自动 unbatch 数据,然后将各个 field 组成各自的 batch 。pad_func 的输入即为 field 的 batch - 形式,输出将被直接作为结果输出。 + :param field_name: 需要调整的 field 的名称。如果 :meth:`Dataset.__getitem__` 方法返回的是字典类型,则可以直接使用对应的 + field 的 key 来表示,如果是嵌套字典,可以使用元组表示多层次的 key,例如 ``{'a': {'b': 1}}`` 中可以使用 ``('a', 'b')``; + 如果 :meth:`Dataset.__getitem__` 返回的是 Sequence 类型,则可以使用 ``'_0'``, ``'_1'`` 表示序列中第 **0** 或 **1** 个元素。 + 如果该 field 在数据中没有找到,则报错;如果 :meth:`Dataset.__getitem__` 返回的是就是整体内容,请使用 "_single" 。 + :param pad_val: 这个 field 的默认 pad 值。如果设置为 ``None``,则表示该 field 不需要 pad , fastNLP 默认只会对可以 pad 的 + field 进行 pad,所以如果对应 field 本身就不是可以 pad 的形式,可以不需要主动设置为 ``None`` 。如果 ``backend`` 为 ``None``, + 该值无意义。 + :param dtype: 对于需要 pad 的 field ,该 field 数据的 ``dtype`` 。 + :param backend: 可选 ``['raw', 'numpy', 'torch', 'paddle', 'jittor', 'oneflow', 'auto']`` ,分别代表,输出为 :class:`list`, + :class:`numpy.ndarray`, :class:`torch.Tensor`, :class:`paddle.Tensor`, :class:`jittor.Var`, :class:`oneflow.Tensor` 类型。 + 若 ``pad_val`` 为 ``None`` ,该值无意义 。 + :param pad_fn: 指定当前 field 的 pad 函数,传入该函数则 ``pad_val``, ``dtype``, ``backend`` 等参数失效。``pad_fn`` 的输入为当前 field 的 + batch 形式。 Collator 将自动 unbatch 数据,然后将各个 field 组成各自的 batch 。 :return: self """ for _, ds in self.iter_datasets(): @@ -385,14 +370,14 @@ class DataBundle: def set_ignore(self, *field_names) -> "DataBundle": """ - 如果有的内容不希望输出,可以在此处进行设置,被设置的 field 将在 batch 的输出中被忽略。 - Example:: + ``DataSet`` 中想要对绑定的 collator 进行调整可以调用此函数。 ``collator`` 为 :class:`~fastNLP.core.collators.Collator` + 时该函数才有效。调用该函数可以设置忽略输出某些 field 的内容,被设置的 field 将在 batch 的输出中被忽略:: - collator.set_ignore('field1', 'field2') + databundle.set_ignore('field1', 'field2') - :param field_names: 需要忽略的 field 的名称。如果 Dataset 的 __getitem__ 方法返回的是 dict 类型的,则可以直接使用对应的 - field 的 key 来表示,如果是 nested 的 dict,可以使用元组来表示,例如 {'a': {'b': 1}} 中的使用 ('a', 'b'); 如果 - __getitem__ 返回的是 Sequence 类型的,则可以使用 '_0', '_1' 表示序列中第 0 或 1 个元素。 + :param field_names: field_name: 需要调整的 field 的名称。如果 :meth:`Dataset.__getitem__` 方法返回的是字典类型,则可以直接使用对应的 + field 的 key 来表示,如果是嵌套字典,可以使用元组表示多层次的 key,例如 ``{'a': {'b': 1}}`` 中可以使用 ``('a', 'b')``; + 如果 :meth:`Dataset.__getitem__` 返回的是 Sequence 类型,则可以使用 ``'_0'``, ``'_1'`` 表示序列中第 **0** 或 **1** 个元素。 :return: self """ for _, ds in self.iter_datasets(): diff --git a/fastNLP/io/embed_loader.py b/fastNLP/io/embed_loader.py index df82643b..650869e2 100644 --- a/fastNLP/io/embed_loader.py +++ b/fastNLP/io/embed_loader.py @@ -1,7 +1,3 @@ -r""" -.. todo:: - doc -""" __all__ = [ "EmbedLoader", "EmbeddingOption", @@ -9,6 +5,7 @@ __all__ = [ import logging import os +from typing import Callable import numpy as np @@ -33,30 +30,30 @@ class EmbeddingOption(Option): class EmbedLoader: r""" - 用于读取预训练的embedding, 读取结果可直接载入为模型参数。 + 用于读取预训练的 embedding, 读取结果可直接载入为模型参数。 """ def __init__(self): super(EmbedLoader, self).__init__() @staticmethod - def load_with_vocab(embed_filepath, vocab, dtype=np.float32, padding='', unknown='', normalize=True, - error='ignore', init_method=None): + def load_with_vocab(embed_filepath: str, vocab, dtype=np.float32, padding: str='', unknown: str='', normalize: bool=True, + error: str='ignore', init_method: Callable=None): r""" - 从embed_filepath这个预训练的词向量中抽取出vocab这个词表的词的embedding。EmbedLoader将自动判断embed_filepath是 - word2vec(第一行只有两个元素)还是glove格式的数据。 + 从 ``embed_filepath`` 这个预训练的词向量中抽取出 ``vocab`` 这个词表的词的 embedding。 :class:`EmbedLoader` 将自动判断 ``embed_filepath`` + 是 **word2vec** (第一行只有两个元素) 还是 **glove** 格式的数据。 - :param str embed_filepath: 预训练的embedding的路径。 - :param vocab: 词表 :class:`~fastNLP.Vocabulary` 类型,读取出现在vocab中的词的embedding。 - 没有出现在vocab中的词的embedding将通过找到的词的embedding的正态分布采样出来,以使得整个Embedding是同分布的。 - :param dtype: 读出的embedding的类型 - :param str padding: 词表中padding的token - :param str unknown: 词表中unknown的token - :param bool normalize: 是否将每个vector归一化到norm为1 - :param str error: `ignore` , `strict` ; 如果 `ignore` ,错误将自动跳过; 如果 `strict` , 错误将抛出。 + :param embed_filepath: 预训练的 embedding 的路径。 + :param vocab: 词表 :class:`~fastNLP.core.Vocabulary` 类型,读取出现在 ``vocab`` 中的词的 embedding。 + 没有出现在 ``vocab`` 中的词的 embedding 将通过找到的词的 embedding 的 *正态分布* 采样出来,以使得整个 Embedding 是同分布的。 + :param dtype: 读出的 embedding 的类型 + :param padding: 词表中 *padding* 的 token + :param unknown: 词表中 *unknown* 的 token + :param normalize: 是否将每个 vector 归一化到 norm 为 1 + :param error: 可以为以下值之一: ``['ignore', 'strict']`` 。如果为 ``ignore`` ,错误将自动跳过;如果是 ``strict`` ,错误将抛出。 这里主要可能出错的地方在于词表有空行或者词表出现了维度不一致。 - :param callable init_method: 传入numpy.ndarray, 返回numpy.ndarray, 用以初始化embedding - :return numpy.ndarray: shape为 [len(vocab), dimension], dimension由pretrain的embedding决定。 + :param init_method: 用于初始化 embedding 的函数。该函数接受一个 :class:`numpy.ndarray` 类型,返回 :class:`numpy.ndarray`。 + :return: 返回类型为 :class:`numpy.ndarray`,形状为 ``[len(vocab), dimension]``,其中 *dimension*由预训练的 embedding 决定。 """ assert isinstance(vocab, Vocabulary), "Only fastNLP.Vocabulary is supported." if not os.path.exists(embed_filepath): @@ -112,20 +109,21 @@ class EmbedLoader: return matrix @staticmethod - def load_without_vocab(embed_filepath, dtype=np.float32, padding='', unknown='', normalize=True, - error='ignore'): + def load_without_vocab(embed_filepath: str, dtype=np.float32, padding: str='', unknown: str='', normalize: bool=True, + error: str='ignore'): r""" - 从embed_filepath中读取预训练的word vector。根据预训练的词表读取embedding并生成一个对应的Vocabulary。 + 从 ``embed_filepath`` 中读取预训练的 word vector。根据预训练的词表读取 embedding 并生成一个对应的 :class:`~fastNLP.core.Vocabulary` 。 - :param str embed_filepath: 预训练的embedding的路径。 - :param dtype: 读出的embedding的类型 - :param str padding: 词表中的padding的token. 并以此用做vocab的padding。 - :param str unknown: 词表中的unknown的token. 并以此用做vocab的unknown。 - :param bool normalize: 是否将每个vector归一化到norm为1 - :param str error: `ignore` , `strict` ; 如果 `ignore` ,错误将自动跳过; 如果 `strict` , 错误将抛出。这里主要可能出错的地 - 方在于词表有空行或者词表出现了维度不一致。 - :return (numpy.ndarray, Vocabulary): Embedding的shape是[词表大小+x, 词表维度], "词表大小+x"是由于最终的大小还取决与 - 是否使用padding, 以及unknown有没有在词表中找到对应的词。 Vocabulary中的词的顺序与Embedding的顺序是一一对应的。 + :param embed_filepath: 预训练的 embedding 的路径。 + :param dtype: 读出的 embedding 的类型 + :param padding: 词表中的 *padding* 的 token。 + :param unknown: 词表中的 *unknown* 的 token。 + :param normalize: 是否将每个 vector 归一化到 norm 为 1 + :param error: 可以为以下值之一: ``['ignore', 'strict']`` 。如果为 ``ignore`` ,错误将自动跳过;如果是 ``strict`` ,错误将抛出。 + 这里主要可能出错的地方在于词表有空行或者词表出现了维度不一致。 + :return: 返回两个结果,第一个返回值为 :class:`numpy.ndarray`,大小为 ``[词表大小+x, 词表维度]`` 。 ``词表大小+x`` 是由于最终的大小还取决于 + 是否使用 ``padding``,以及 ``unknown`` 有没有在词表中找到对应的词。 第二个返回值为 :class:`~fastNLP.core.Vocabulary` 类型的词表,其中 + 词的顺序与 embedding 的顺序是一一对应的。 """ vocab = Vocabulary(padding=padding, unknown=unknown) diff --git a/fastNLP/io/file_reader.py b/fastNLP/io/file_reader.py index 2df61e17..37bdbce9 100644 --- a/fastNLP/io/file_reader.py +++ b/fastNLP/io/file_reader.py @@ -1,7 +1,3 @@ -r"""undocumented -此模块用于给其它模块提供读取文件的函数,没有为用户提供 API -""" - __all__ = [] import json diff --git a/fastNLP/io/file_utils.py b/fastNLP/io/file_utils.py index b982af54..3f37ff19 100644 --- a/fastNLP/io/file_utils.py +++ b/fastNLP/io/file_utils.py @@ -1,8 +1,3 @@ -r""" -.. todo:: - doc -""" - __all__ = [ "cached_path", "get_filepath", @@ -160,21 +155,16 @@ FASTNLP_EXTEND_EMBEDDING_URL = {'elmo': 'fastnlp_elmo_url.txt', def cached_path(url_or_filename: str, cache_dir: str = None, name=None) -> Path: r""" - 给定一个url,尝试通过url中的解析出来的文件名字filename到{cache_dir}/{name}/{filename}下寻找这个文件, - - 1. 如果cache_dir=None, 则cache_dir=~/.fastNLP/; 否则cache_dir=cache_dir - 2. 如果name=None, 则没有中间的{name}这一层结构;否者中间结构就为{name} - - 如果有该文件,就直接返回路径 + 给定一个 url,尝试通过 url 中解析出来的文件名字 filename 到 ``{cache_dir}/{name}/{filename}`` 下寻找这个文件或文件夹: - 如果没有该文件,则尝试用传入的url下载 + 1. 如果 ``cache_dir`` 为 ``None``,则默认为 ``~/.fastNLP/``; + 2. 如果 ``name=None`` ,则没有中间的 {name} 这一层结构。 - 或者文件名(可以是具体的文件名,也可以是文件夹),先在cache_dir下寻找该文件是否存在,如果不存在则去下载, 并 - 将文件放入到cache_dir中. + 如果有该文件,就直接返回路径;如果没有该文件,则尝试用传入的 url 下载,并将文件放入 ``cache_dir`` 中。 - :param str url_or_filename: 文件的下载url或者文件名称。 - :param str cache_dir: 文件的缓存文件夹。如果为None,将使用"~/.fastNLP"这个默认路径 - :param str name: 中间一层的名称。如embedding, dataset + :param url_or_filename: 文件的下载 url 或者文件名称。 + :param cache_dir: 文件的缓存文件夹。如果为 ``None``,将使 ``"~/.fastNLP`` 这个默认路径 + :param name: 中间一层的名称。如 embedding, dataset :return: """ if cache_dir is None: @@ -205,17 +195,10 @@ def cached_path(url_or_filename: str, cache_dir: str = None, name=None) -> Path: def get_filepath(filepath): r""" - 如果filepath为文件夹, - - 如果内含多个文件, 返回filepath - - 如果只有一个文件, 返回filepath + filename - - 如果filepath为文件 - - 返回filepath + 如果 ``filepath`` 为文件夹且包含多个文件,则直接返回 ``filepath``;反之若只包含一个文件,返回该文件的路径 ``{filepath}/{filename}``。 + 如果 ``filepath`` 为一个文件,也会直接返回 ``filepath``。 - :param str filepath: 路径 + :param filepath: 路径 :return: """ if os.path.isdir(filepath): @@ -232,9 +215,7 @@ def get_filepath(filepath): def get_cache_path(): r""" - 获取fastNLP默认cache的存放路径, 如果将FASTNLP_CACHE_PATH设置在了环境变量中,将使用环境变量的值,使得不用每个用户都去下载。 - - :return str: 存放路径 + 获取 **fastNLP** 默认 cache 的存放路径, 如果将 ``FASTNLP_CACHE_PATH`` 设置在了环境变量中,将使用环境变量的值,使得不用每个用户都去下载。 """ if 'FASTNLP_CACHE_DIR' in os.environ: fastnlp_cache_dir = os.environ.get('FASTNLP_CACHE_DIR') @@ -342,10 +323,10 @@ def _get_dataset_url(name, dataset_dir: dict = None): def split_filename_suffix(filepath): r""" - 给定filepath 返回对应的name和suffix. 如果后缀是多个点,仅支持.tar.gz类型 + 给定 ``filepath`` 返回对应的文件名和后缀。如果后缀是多个点,仅支持 **.tar.gz** 类型 :param filepath: 文件路径 - :return: filename, suffix + :return: 文件名 ``filename`` 和后缀 ``suffix`` """ filename = os.path.basename(filepath) if filename.endswith('.tar.gz'): @@ -355,10 +336,10 @@ def split_filename_suffix(filepath): def get_from_cache(url: str, cache_dir: Path = None) -> Path: r""" - 尝试在cache_dir中寻找url定义的资源; 如果没有找到; 则从url下载并将结果放在cache_dir下,缓存的名称由url的结果推断而来。会将下载的 - 文件解压,将解压后的文件全部放在cache_dir文件夹中。 + 尝试在 ``cache_dir``中寻找 ``url`` 定义的资源,如果没有找到,则从 ``url`` 下载并将结果放在 ``cache_dir`` 下, + 缓存的名称由 ``url`` 的结果推断而来。会将下载的文件解压,将解压后的文件全部放在 ``cache_dir`` 文件夹中。 - 如果从url中下载的资源解压后有多个文件,则返回目录的路径; 如果只有一个资源文件,则返回具体的路径。 + 如果从 ``url``中下载的资源解压后有多个文件,则返回目录的路径;如果只有一个资源文件,则返回具体的路径。 :param url: 资源的 url :param cache_dir: cache 目录 diff --git a/fastNLP/io/loader/__init__.py b/fastNLP/io/loader/__init__.py index ebd56330..04752a96 100644 --- a/fastNLP/io/loader/__init__.py +++ b/fastNLP/io/loader/__init__.py @@ -1,8 +1,8 @@ r""" -Loader用于读取数据,并将内容读取到 :class:`~fastNLP.DataSet` 或者 :class:`~fastNLP.io.DataBundle` 中。所有的Loader都支持以下的 -三个方法: ``__init__`` , ``_load`` , ``loads`` . 其中 ``__init__(...)`` 用于申明读取参数,以及说明该Loader支持的数据格式, -读取后 :class:`~fastNLP.DataSet` 中的 `field` ; ``_load(path)`` 方法传入文件路径读取单个文件,并返回 :class:`~fastNLP.DataSet` ; -``load(paths)`` 用于读取文件夹下的文件,并返回 :class:`~fastNLP.io.DataBundle` 类型的对象 , load()方法支持以下几种类型的参数: +**Loader** 用于读取数据,并将内容读取到 :class:`~fastNLP.core.DataSet` 或者 :class:`~fastNLP.io.DataBundle` 中。所有的 ``Loader`` 都支持以下的 +三个方法: ``__init__`` , ``_load`` , ``loads`` . 其中 ``__init__(...)`` 用于申明读取参数,以及说明该 ``Loader`` 支持的数据格式, +读取后 :class:`~fastNLP.core.DataSet` 中的 `field` ; ``_load(path)`` 方法传入文件路径读取单个文件,并返回 :class:`~fastNLP.core.DataSet` ; +``load(paths)`` 用于读取文件夹下的文件,并返回 :class:`~fastNLP.io.DataBundle` 类型的对象 , load()方法支持以下几种类型的参数: 0.传入None 将尝试自动下载数据集并缓存。但不是所有的数据都可以直接下载。 @@ -38,10 +38,7 @@ Loader用于读取数据,并将内容读取到 :class:`~fastNLP.DataSet` 或 在 Loader().load(paths) 返回的 `data_bundle` 中可以用 ``data_bundle.get_dataset('train')`` , ``data_bundle.get_dataset('dev')`` , ``data_bundle.get_dataset('test')`` 来获取对应的 `dataset` -fastNLP 目前提供了如下的 Loader - - - +**fastNLP** 目前提供了如下的 Loader: """ __all__ = [ diff --git a/fastNLP/io/loader/classification.py b/fastNLP/io/loader/classification.py index 2ae0b163..99c42041 100644 --- a/fastNLP/io/loader/classification.py +++ b/fastNLP/io/loader/classification.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "CLSBaseLoader", "YelpFullLoader", @@ -30,22 +28,18 @@ from .loader import Loader from fastNLP.core.dataset import Instance, DataSet from fastNLP.core.log import logger - -# from ...core._logger import log - - class CLSBaseLoader(Loader): r""" - 文本分类Loader的一个基类 + 文本分类 Loader 的一个基类 - 原始数据中内容应该为, 每一行为一个sample,第一个逗号之前为target,第一个逗号之后为文本内容。 + 原始数据中内容应该为:每一行为一个 sample ,第一个逗号之前为 **target** ,第一个逗号之后为 **文本内容** 。 Example:: "1","I got 'new' tires from the..." "1","Don't waste your time..." - 读取的DataSet将具备以下的数据结构 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words", "target" @@ -124,32 +118,36 @@ def _split_dev(dataset_name, data_dir, dev_ratio=0.0, re_download=False, suffix= class AGsNewsLoader(CLSBaseLoader): - def download(self): - r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 + """ + **AG's News** 数据集的 **Loader**,如果您使用了这个数据集,请引用以下的文章 Xiang Zhang, Junbo Zhao, Yann LeCun. Character-level Convolutional Networks for Text Classification. Advances in Neural Information Processing Systems 28 (NIPS 2015) + """ + def download(self): + r""" + 自动下载数据集。 - :return: str, 数据集的目录地址 + :return: 数据集的目录地址 """ return self._get_dataset_path(dataset_name='ag-news') class DBPediaLoader(CLSBaseLoader): - def download(self, dev_ratio: float = 0.0, re_download: bool = False): - r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 + """ + **DBpedia** 数据集的 **Loader**。如果您使用了这个数据集,请引用以下的文章 Xiang Zhang, Junbo Zhao, Yann LeCun. Character-level Convolutional Networks for Text Classification. Advances in Neural Information Processing Systems 28 (NIPS 2015) + """ + def download(self, dev_ratio: float = 0.0, re_download: bool = False): + r""" + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv - - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = 'dbpedia' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -163,15 +161,18 @@ class DBPediaLoader(CLSBaseLoader): class IMDBLoader(CLSBaseLoader): r""" - 原始数据中内容应该为, 每一行为一个sample,制表符之前为target,制表符之后为文本内容。 + **IMDb** 数据集的 **Loader** ,如果您使用了这个数据集,请引用以下的文章 + + http://www.aclweb.org/anthology/P11-1015。 + + 原始数据中内容应该为:每一行为一个 sample ,制表符之前为 **target** ,制表符之后为 **文本内容** 。 Example:: neg Alan Rickman & Emma... neg I have seen this... - IMDBLoader读取后的数据将具有以下两列内容: raw_words: str, 需要分类的文本; target: str, 文本的标签 - 读取的DataSet具备以下的结构: + **IMDBLoader** 读取后的 :class:`~fastNLP.core.DataSet` 将具有以下两列内容: ``raw_words`` 代表需要分类的文本,``target`` 代表文本的标签: .. csv-table:: :header: "raw_words", "target" @@ -187,15 +188,13 @@ class IMDBLoader(CLSBaseLoader): def download(self, dev_ratio: float = 0.0, re_download=False): r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 + 自动下载数据集。 - http://www.aclweb.org/anthology/P11-1015 + 根据 ``dev_ratio`` 的值随机将 train 中的数据取出一部分作为 dev 数据。 - 根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。下载完成后不从train中切分dev - - :param float dev_ratio: 如果路径中没有dev.txt。从train划分多少作为dev的数据. 如果为0,则不划分dev - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有 ``dev.txt`` ,从 train 划分多少作为 dev 的数据。 如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = 'aclImdb' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -209,23 +208,25 @@ class IMDBLoader(CLSBaseLoader): class SSTLoader(Loader): r""" - 原始数据中内容应该为: + **SST** 数据集的 **Loader**,如果您使用了这个数据集,请引用以下的文章 - Example:: + https://nlp.stanford.edu/~socherr/EMNLP2013_RNTN.pdf + + 原始数据中内容应该为:: (2 (3 (3 Effective) (2 but)) (1 (1 too-tepid)... (3 (3 (2 If) (3 (2 you) (3 (2 sometimes)... - 读取之后的DataSet具有以下的结构 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: - .. csv-table:: 下面是使用SSTLoader读取的DataSet所具备的field + .. csv-table:: 下面是使用 SSTLoader 读取的 DataSet 所具备的 field :header: "raw_words" "(2 (3 (3 Effective) (2 but)) (1 (1 too-tepid)..." "(3 (3 (2 If) (3 (2 you) (3 (2 sometimes) ..." "..." - raw_words列是str。 + ``raw_words`` 列是 :class:`str` 。 """ @@ -249,30 +250,29 @@ class SSTLoader(Loader): def download(self): r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 - - https://nlp.stanford.edu/~socherr/EMNLP2013_RNTN.pdf + 自动下载数据集。 - :return: str, 数据集的目录地址 + :return: 数据集的目录地址 """ output_dir = self._get_dataset_path(dataset_name='sst') return output_dir class YelpFullLoader(CLSBaseLoader): - def download(self, dev_ratio: float = 0.0, re_download: bool = False): - r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 + """ + **Yelp Review Full** 数据集的 **Loader**,如果您使用了这个数据集,请引用以下的文章 Xiang Zhang, Junbo Zhao, Yann LeCun. Character-level Convolutional Networks for Text Classification. Advances in Neural Information Processing Systems 28 (NIPS 2015) + """ + def download(self, dev_ratio: float = 0.0, re_download: bool = False): + r""" + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv - - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = 'yelp-review-full' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -285,19 +285,20 @@ class YelpFullLoader(CLSBaseLoader): class YelpPolarityLoader(CLSBaseLoader): - def download(self, dev_ratio: float = 0.0, re_download: bool = False): - r""" - 自动下载数据集,如果你使用了这个数据集,请引用以下的文章 + """ + **Yelp Review Polarity** 数据集的 **Loader**,如果您使用了这个数据集,请引用以下的文章 Xiang Zhang, Junbo Zhao, Yann LeCun. Character-level Convolutional Networks for Text Classification. Advances in Neural Information Processing Systems 28 (NIPS 2015) + """ + def download(self, dev_ratio: float = 0.0, re_download: bool = False): + r""" + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv - - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = 'yelp-review-polarity' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -311,7 +312,12 @@ class YelpPolarityLoader(CLSBaseLoader): class SST2Loader(Loader): r""" - 原始数据中内容为:第一行为标题(具体内容会被忽略),之后一行为一个sample,第一个制表符之前被认为是句子,第一个制表符之后认为是label + **SST-2** 数据集的 **Loader**,如果您使用了该数据集,请引用以下的文章 + + https://nlp.stanford.edu/pubs/SocherBauerManningNg_ACL2013.pdf + + 原始数据中内容应该为:第一行为标题(具体内容会被忽略),之后每一行为一个 sample ,第一个制表符之前是 **句子** , + 第一个制表符之后认为是 **label** 。 Example:: @@ -319,7 +325,7 @@ class SST2Loader(Loader): it 's a charming and often affecting journey . 1 unflinchingly bleak and desperate 0 - 读取之后DataSet将如下所示 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words", "target" @@ -328,7 +334,7 @@ class SST2Loader(Loader): "unflinchingly bleak and desperate", "0" "..." - test的DataSet没有target列。 + 测试集的 :class:`~fastNLP.core.DataSet` 没有 ``target`` 列。 """ def __init__(self): @@ -366,8 +372,8 @@ class SST2Loader(Loader): def download(self): r""" - 自动下载数据集,如果你使用了该数据集,请引用以下的文章 - https://nlp.stanford.edu/pubs/SocherBauerManningNg_ACL2013.pdf + 自动下载数据集。 + :return: """ output_dir = self._get_dataset_path(dataset_name='sst-2') @@ -376,8 +382,11 @@ class SST2Loader(Loader): class ChnSentiCorpLoader(Loader): r""" - 支持读取的数据的格式为,第一行为标题(具体内容会被忽略),之后一行为一个sample,第一个制表符之前被认为是label,第 - 一个制表符之后认为是句子 + **ChnSentiCorp** 数据集的 **Loader**,该数据取自 https://github.com/pengming617/bert_classification/tree/master/data,在 + https://arxiv.org/pdf/1904.09223.pdf 与 https://arxiv.org/pdf/1906.08101.pdf 有使用。 + + 支持读取的数据的格式为:第一行为标题(具体内容会被忽略),之后每一行为一个 sample,第一个制表符之前被认为是 **label** ,第 + 一个制表符之后认为是 **句子** 。 Example:: @@ -385,7 +394,7 @@ class ChnSentiCorpLoader(Loader): 1 基金痛所有投资项目一样,必须先要有所了解... 1 系统很好装,LED屏是不错,就是16比9的比例... - 读取后的DataSet具有以下的field + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars", "target" @@ -421,10 +430,9 @@ class ChnSentiCorpLoader(Loader): def download(self) -> str: r""" - 自动下载数据,该数据取自https://github.com/pengming617/bert_classification/tree/master/data,在 - https://arxiv.org/pdf/1904.09223.pdf与https://arxiv.org/pdf/1906.08101.pdf有使用 + 自动下载数据。 - :return: + :return: 数据集的目录地址 """ output_dir = self._get_dataset_path('chn-senti-corp') return output_dir @@ -432,14 +440,17 @@ class ChnSentiCorpLoader(Loader): class THUCNewsLoader(Loader): r""" - 数据集简介:document-level分类任务,新闻10分类 - 原始数据内容为:每行一个sample,第一个 "\\t" 之前为target,第一个 "\\t" 之后为raw_words + **THUCNews** 数据集的 **Loader**,该数据取自 + http://thuctc.thunlp.org/#%E4%B8%AD%E6%96%87%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB%E6%95%B0%E6%8D%AE%E9%9B%86THUCNews + + 数据用于 document-level 分类任务,新闻 10 分类。 + 原始数据内容为:每行一个 sample,第一个 ``"\t"`` 之前为 **target** ,第一个 ``"\t"`` 之后为 **raw_words** 。 Example:: 体育 调查-您如何评价热火客场胜绿军总分3-1夺赛点?... - 读取后的Dataset将具有以下数据结构: + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words", "target" @@ -466,11 +477,9 @@ class THUCNewsLoader(Loader): def download(self) -> str: r""" - 自动下载数据,该数据取自 - - http://thuctc.thunlp.org/#%E4%B8%AD%E6%96%87%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB%E6%95%B0%E6%8D%AE%E9%9B%86THUCNews + 自动下载数据。 - :return: + :return: 数据集目录地址 """ output_dir = self._get_dataset_path('thuc-news') return output_dir @@ -478,8 +487,8 @@ class THUCNewsLoader(Loader): class WeiboSenti100kLoader(Loader): r""" - 别名: - 数据集简介:微博sentiment classification,二分类 + **WeiboSenti100k** 数据集的 **Loader**,该数据取自 https://github.com/SophonPlus/ChineseNlpCorpus/, + 在 https://arxiv.org/abs/1906.08101 有使用。微博 sentiment classification,二分类。 Example:: @@ -487,7 +496,7 @@ class WeiboSenti100kLoader(Loader): 1 多谢小莲,好运满满[爱你] 1 能在他乡遇老友真不赖,哈哈,珠儿,我也要用... - 读取后的Dataset将具有以下数据结构: + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars", "target" @@ -515,28 +524,29 @@ class WeiboSenti100kLoader(Loader): def download(self) -> str: r""" - 自动下载数据,该数据取自 https://github.com/SophonPlus/ChineseNlpCorpus/ - 在 https://arxiv.org/abs/1906.08101 有使用 - :return: + 自动下载数据。 + + :return: 数据集目录地址 """ output_dir = self._get_dataset_path('weibo-senti-100k') return output_dir class MRLoader(CLSBaseLoader): + """ + **MR** 数据集的 **Loader** + """ def __init__(self): super(MRLoader, self).__init__() def download(self, dev_ratio: float = 0.0, re_download: bool = False) -> str: r""" - 自动下载数据集 + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv - - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = r'mr' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -549,19 +559,20 @@ class MRLoader(CLSBaseLoader): class R8Loader(CLSBaseLoader): + """ + **R8** 数据集的 **Loader** + """ def __init__(self): super(R8Loader, self).__init__() def download(self, dev_ratio: float = 0.0, re_download: bool = False) -> str: r""" - 自动下载数据集 - - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = r'R8' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -574,19 +585,20 @@ class R8Loader(CLSBaseLoader): class R52Loader(CLSBaseLoader): + """ + **R52** 数据集的 **Loader** + """ def __init__(self): super(R52Loader, self).__init__() def download(self, dev_ratio: float = 0.0, re_download: bool = False) -> str: r""" - 自动下载数据集 + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv - - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = r'R52' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -599,19 +611,20 @@ class R52Loader(CLSBaseLoader): class NG20Loader(CLSBaseLoader): + """ + **NG20** 数据集的 **Loader** + """ def __init__(self): super(NG20Loader, self).__init__() def download(self, dev_ratio: float = 0.0, re_download: bool = False) -> str: r""" - 自动下载数据集 - - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = r'20ng' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -624,19 +637,20 @@ class NG20Loader(CLSBaseLoader): class OhsumedLoader(CLSBaseLoader): + """ + **Ohsumed** 数据集的 **Loader** + """ def __init__(self): super(OhsumedLoader, self).__init__() def download(self, dev_ratio: float = 0.0, re_download: bool = False) -> str: r""" - 自动下载数据集 - - 如果dev_ratio不等于0,则根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。 - 下载完成后在output_dir中有train.csv, test.csv, dev.csv三个文件。否则只有train.csv和test.csv + 自动下载数据集。下载完成后在 ``output_dir`` 中有 ``train.csv`` , ``test.csv`` , ``dev.csv`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.csv`` 和 ``test.csv`` 。 - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ dataset_name = r'ohsumed' data_dir = self._get_dataset_path(dataset_name=dataset_name) diff --git a/fastNLP/io/loader/conll.py b/fastNLP/io/loader/conll.py index 0b597398..ef209fb4 100644 --- a/fastNLP/io/loader/conll.py +++ b/fastNLP/io/loader/conll.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "ConllLoader", "Conll2003Loader", @@ -17,6 +15,7 @@ import os import random import shutil import time +from typing import List from .loader import Loader from ..file_reader import _read_conll @@ -26,9 +25,7 @@ from fastNLP.core.dataset import DataSet, Instance class ConllLoader(Loader): r""" - ConllLoader支持读取的数据格式: 以空行隔开两个sample,除了分割行,每一行用空格或者制表符隔开不同的元素。如下例所示: - - Example:: + :class:`ConllLoader` 支持读取的数据格式:以空行隔开两个 sample,除了分割行之外的每一行用空格或者制表符隔开不同的元素。如下例所示:: # 文件中的内容 Nadim NNP B-NP B-PER @@ -48,19 +45,16 @@ class ConllLoader(Loader): # 如果用以下的参数读取,返回的DataSet将包含raw_words, pos和ner三个field dataset = ConllLoader(headers=['raw_words', 'pos', 'ner'], indexes=[0, 1, 3])._load('/path/to/train.conll') - ConllLoader返回的DataSet的field由传入的headers确定。 + :class:`ConllLoader` 返回的 :class:`~fastNLP.core.DataSet` 的 `field` 由传入的 ``headers`` 确定。 + :param headers: 每一列数据的名称, ``header`` 与 ``indexes`` 一一对应 + :param sep: 指定分隔符,默认为制表符 + :param indexes: 需要保留的数据列下标,从 **0** 开始。若为 ``None`` ,则所有列都保留。 + :param dropna: 是否忽略非法数据,若为 ``False`` ,则遇到非法数据时抛出 :class:`ValueError` 。 + :param drophashtag: 是否忽略以 ``#`` 开头的句子。 """ - def __init__(self, headers, sep=None, indexes=None, dropna=True, drophash=True): - r""" - - :param list headers: 每一列数据的名称,需为List or Tuple of str。``header`` 与 ``indexes`` 一一对应 - :param str sep: 指定分隔符,默认为制表符 - :param list indexes: 需要保留的数据列下标,从0开始。若为 ``None`` ,则所有列都保留。Default: ``None`` - :param bool dropna: 是否忽略非法数据,若 ``False`` ,遇到非法数据时抛出 ``ValueError`` 。Default: ``True`` - :param bool drophashtag: 是否忽略以 ``#`` 开头的句子。 - """ + def __init__(self, headers: List[str], sep: str=None, indexes: List[int]=None, dropna: bool=True, drophash: bool=True): super(ConllLoader, self).__init__() if not isinstance(headers, (list, tuple)): raise TypeError( @@ -93,8 +87,9 @@ class ConllLoader(Loader): class Conll2003Loader(ConllLoader): r""" - 用于读取conll2003任务的数据。数据的内容应该类似与以下的内容, 第一列为raw_words, 第二列为pos, 第三列为chunking,第四列为ner。 - 数据中以"-DOCSTART-"开头的行将被忽略,因为该符号在conll 2003中被用为文档分割符。 + 用于读取 **conll2003** 任务的数据。数据的内容应该类似于以下的内容:第一列为 **raw_words** ,第二列为 **pos** , + 第三列为 **chunking** ,第四列为 **ner** 。 + 数据中以 ``"-DOCSTART-"`` 开头的行将被忽略,因为该符号在 **conll2003** 中被用为文档分割符。 Example:: @@ -108,9 +103,9 @@ class Conll2003Loader(ConllLoader): 1996-12-06 CD I-NP O ... - 返回的DataSet的内容为 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: - .. csv-table:: 下面是Conll2003Loader加载后数据具备的结构。 + .. csv-table:: 下面是 Conll2003Loader 加载后数据具备的结构。 :header: "raw_words", "pos", "chunk", "ner" "[Nadim, Ladki]", "[NNP, NNP]", "[B-NP, I-NP]", "[B-PER, I-PER]" @@ -152,10 +147,9 @@ class Conll2003Loader(ConllLoader): class Conll2003NERLoader(ConllLoader): r""" - 用于读取conll2003任务的NER数据。每一行有4列内容,空行意味着隔开两个句子 + 用于读取 **conll2003** 任务的 NER 数据。每一行有 4 列内容,空行意味着隔开两个句子。 - 支持读取的内容如下 - Example:: + 支持读取的内容如下:: Nadim NNP B-NP B-PER Ladki NNP I-NP I-PER @@ -167,9 +161,9 @@ class Conll2003NERLoader(ConllLoader): 1996-12-06 CD I-NP O ... - 返回的DataSet的内容为 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: - .. csv-table:: 下面是Conll2003Loader加载后数据具备的结构, target是BIO2编码 + .. csv-table:: 下面是 Conll2003Loader 加载后数据具备的结构, target 是 BIO2 编码 :header: "raw_words", "target" "[Nadim, Ladki]", "[B-PER, I-PER]" @@ -213,18 +207,16 @@ class Conll2003NERLoader(ConllLoader): class OntoNotesNERLoader(ConllLoader): r""" - 用以读取OntoNotes的NER数据,同时也是Conll2012的NER任务数据。将OntoNote数据处理为conll格式的过程可以参考 - https://github.com/yhcc/OntoNotes-5.0-NER。OntoNoteNERLoader将取第4列和第11列的内容。 - - 读取的数据格式为: + 用以读取 **OntoNotes** 的 NER 数据,同时也是 **Conll2012** 的 NER 任务数据。将 **OntoNote** 数据处理为 conll 格式的过程可以参考 + https://github.com/yhcc/OntoNotes-5.0-NER。:class:`OntoNotesNERLoader` 将取第 **4** 列和第 **11** 列的内容。 - Example:: + 读取的数据格式为:: bc/msnbc/00/msnbc_0000 0 0 Hi UH (TOP(FRAG(INTJ*) - - - Dan_Abrams * - bc/msnbc/00/msnbc_0000 0 1 everyone NN (NP*) - - - Dan_Abrams * - ... - 返回的DataSet的内容为 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words", "target" @@ -291,7 +283,8 @@ class OntoNotesNERLoader(ConllLoader): class CTBLoader(Loader): r""" - 支持加载的数据应该具备以下格式, 其中第二列为词语,第四列为pos tag,第七列为依赖树的head,第八列为依赖树的label + **CTB** 数据集的 **Loader**。支持加载的数据应该具备以下格式, 其中第二列为 **词语** ,第四列为 **pos tag** ,第七列为 **依赖树的 head** , + 第八列为 **依赖树的 label** 。 Example:: @@ -306,7 +299,7 @@ class CTBLoader(Loader): 3 12月 _ NT NT _ 7 dep _ _ ... - 读取之后DataSet具备的格式为 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words", "pos", "dep_head", "dep_label" @@ -335,30 +328,30 @@ class CTBLoader(Loader): 由于版权限制,不能提供自动下载功能。可参考 https://catalog.ldc.upenn.edu/LDC2013T21 - - :return: """ raise RuntimeError("CTB cannot be downloaded automatically.") class CNNERLoader(Loader): - def _load(self, path: str): - r""" - 支持加载形如以下格式的内容,一行两列,以空格隔开两个sample + r""" + 支持加载形如以下格式的内容,一行两列,以空格隔开两个 sample - Example:: + Example:: - 我 O - 们 O - 变 O - 而 O - 以 O - 书 O - 会 O - ... + 我 O + 们 O + 变 O + 而 O + 以 O + 书 O + 会 O + ... - :param str path: 文件路径 - :return: DataSet,包含raw_words列和target列 + """ + def _load(self, path: str): + """ + :param path: 文件路径 + :return: :class:`~fastNLP.core.DataSet` ,包含 ``raw_words`` 列和 ``target`` 列 """ ds = DataSet() with open(path, 'r', encoding='utf-8') as f: @@ -382,9 +375,11 @@ class CNNERLoader(Loader): class MsraNERLoader(CNNERLoader): r""" - 读取MSRA-NER数据,数据中的格式应该类似与下列的内容 - - Example:: + 读取 **MSRA-NER** 数据,如果您要使用该数据,请引用以下的文章: + + Gina-Anne Levow, 2006, The Third International Chinese Language Processing Bakeoff: Word Segmentation and Named Entity Recognition. + + 数据中的格式应该类似于下列的内容:: 把 O 欧 B-LOC @@ -404,7 +399,7 @@ class MsraNERLoader(CNNERLoader): ... - 读取后的DataSet包含以下的field + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars", "target" @@ -420,15 +415,14 @@ class MsraNERLoader(CNNERLoader): def download(self, dev_ratio: float = 0.1, re_download: bool = False) -> str: r""" - 自动下载MSAR-NER的数据,如果你使用该数据,请引用 Gina-Anne Levow, 2006, The Third International Chinese Language - Processing Bakeoff: Word Segmentation and Named Entity Recognition. + 自动下载 **MSAR-NER** 的数据。 - 根据dev_ratio的值随机将train中的数据取出一部分作为dev数据。下载完成后在output_dir中有train.conll, test.conll, - dev.conll三个文件。 + 下载完成后在 ``output_dir`` 中有 ``train.conll`` , ``test.conll`` , ``dev.conll`` 三个文件。 + 如果 ``dev_ratio`` 为 0,则只有 ``train.conll`` 和 ``test.conll`` 。 - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str, 数据集的目录地址 + :param dev_ratio: 如果路径中没有验证集 ,从 train 划分多少作为 dev 的数据。如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 :return: """ dataset_name = 'msra-ner' @@ -470,9 +464,11 @@ class MsraNERLoader(CNNERLoader): class WeiboNERLoader(CNNERLoader): r""" - 读取WeiboNER数据,数据中的格式应该类似与下列的内容 - - Example:: + 读取 **WeiboNER** 数据,如果您要使用该数据,请引用以下的文章: + + Nanyun Peng and Mark Dredze, 2015, Named Entity Recognition for Chinese Social Media with Jointly Trained Embeddings. + + 数据中的格式应该类似与下列的内容:: 老 B-PER.NOM 百 I-PER.NOM @@ -482,7 +478,7 @@ class WeiboNERLoader(CNNERLoader): ... - 读取后的DataSet包含以下的field + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: @@ -498,10 +494,9 @@ class WeiboNERLoader(CNNERLoader): def download(self) -> str: r""" - 自动下载Weibo-NER的数据,如果你使用了该数据,请引用 Nanyun Peng and Mark Dredze, 2015, Named Entity Recognition for - Chinese Social Media with Jointly Trained Embeddings. + 自动下载 **Weibo-NER** 的数据。 - :return: str + :return: 数据集目录地址 """ dataset_name = 'weibo-ner' data_dir = self._get_dataset_path(dataset_name=dataset_name) @@ -511,9 +506,7 @@ class WeiboNERLoader(CNNERLoader): class PeopleDailyNERLoader(CNNERLoader): r""" - 支持加载的数据格式如下 - - Example:: + 加载 **People's Daily NER** 数据集的 **Loader** 。支持加载的数据格式如下:: 中 B-ORG 共 I-ORG @@ -524,9 +517,9 @@ class PeopleDailyNERLoader(CNNERLoader): 中 B-ORG ... - 读取后的DataSet包含以下的field + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: - .. csv-table:: target列是基于BIO的编码方式 + .. csv-table:: target 列是基于 BIO 的编码方式 :header: "raw_chars", "target" "['中', '共', '中', '央']", "['B-ORG', 'I-ORG', 'I-ORG', 'I-ORG']" @@ -538,6 +531,11 @@ class PeopleDailyNERLoader(CNNERLoader): super().__init__() def download(self) -> str: + """ + 自动下载数据集。 + + :return: 数据集目录地址 + """ dataset_name = 'peopledaily' data_dir = self._get_dataset_path(dataset_name=dataset_name) diff --git a/fastNLP/io/loader/csv.py b/fastNLP/io/loader/csv.py index debd5222..09a60694 100644 --- a/fastNLP/io/loader/csv.py +++ b/fastNLP/io/loader/csv.py @@ -1,9 +1,9 @@ -r"""undocumented""" - __all__ = [ "CSVLoader", ] +from typing import List + from .loader import Loader from ..file_reader import _read_csv from fastNLP.core.dataset import DataSet, Instance @@ -11,19 +11,15 @@ from fastNLP.core.dataset import DataSet, Instance class CSVLoader(Loader): r""" - 读取CSV格式的数据集, 返回 ``DataSet`` 。 + 读取CSV格式的数据集, 返回 :class:`~fastNLP.core.DataSet` 。 + :param headers: CSV文件的文件头,定义每一列的属性名称,即返回的 :class:`~fastNLP.core.DataSet` 中 ``field`` 的名称。 + 若为 ``None`` ,则将读入文件的第一行视作 ``headers`` 。 + :param sep: CSV文件中列与列之间的分隔符。 + :param dropna: 是否忽略非法数据,若为 ``True`` 则忽略;若为 ``False`` 则在遇到非法数据时抛出 :class:`ValueError`。 """ - def __init__(self, headers=None, sep=",", dropna=False): - r""" - - :param List[str] headers: CSV文件的文件头.定义每一列的属性名称,即返回的DataSet中`field`的名称 - 若为 ``None`` ,则将读入文件的第一行视作 ``headers`` . Default: ``None`` - :param str sep: CSV文件中列与列之间的分隔符. Default: "," - :param bool dropna: 是否忽略非法数据,若 ``True`` 则忽略,若 ``False`` ,在遇到非法数据时,抛出 ``ValueError`` . - Default: ``False`` - """ + def __init__(self, headers: List[str]=None, sep: str=",", dropna: bool=False): super().__init__() self.headers = headers self.sep = sep diff --git a/fastNLP/io/loader/cws.py b/fastNLP/io/loader/cws.py index d88d6a00..f7bdbcb5 100644 --- a/fastNLP/io/loader/cws.py +++ b/fastNLP/io/loader/cws.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "CWSLoader" ] @@ -16,15 +14,16 @@ from fastNLP.core.dataset import DataSet, Instance class CWSLoader(Loader): r""" - CWSLoader支持的数据格式为,一行一句话,不同词之间用空格隔开, 例如: + **Chinese word segmentor** 的 **Loader** 。如果您使用了该数据集,请引用以下的文章:Thomas Emerson, The Second International Chinese Word Segmentation Bakeoff, + 2005. 更多信息可以在 http://sighan.cs.uchicago.edu/bakeoff2005/ 查看。 - Example:: + :class:`CWSLoader` 支持的数据格式为:一行一句话,不同词之间用空格隔开,例如:: 上海 浦东 开发 与 法制 建设 同步 新华社 上海 二月 十日 电 ( 记者 谢金虎 、 张持坚 ) ... - 该Loader读取后的DataSet具有如下的结构 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words" @@ -32,14 +31,11 @@ class CWSLoader(Loader): "上海 浦东 开发 与 法制 建设 同步" "新华社 上海 二月 十日 电 ( 记者 谢金虎 、 张持坚 )" "..." - + + :param dataset_name: data 的名称,支持 ``['pku', 'msra', 'cityu'(繁体), 'as'(繁体), None]`` """ def __init__(self, dataset_name: str = None): - r""" - - :param str dataset_name: data的名称,支持pku, msra, cityu(繁体), as(繁体), None - """ super().__init__() datanames = {'pku': 'cws-pku', 'msra': 'cws-msra', 'as': 'cws-as', 'cityu': 'cws-cityu'} if dataset_name in datanames: @@ -58,12 +54,11 @@ class CWSLoader(Loader): def download(self, dev_ratio=0.1, re_download=False) -> str: r""" - 如果你使用了该数据集,请引用以下的文章:Thomas Emerson, The Second International Chinese Word Segmentation Bakeoff, - 2005. 更多信息可以在http://sighan.cs.uchicago.edu/bakeoff2005/查看 + 自动下载数据集。 - :param float dev_ratio: 如果路径中没有dev集,从train划分多少作为dev的数据. 如果为0,则不划分dev。 - :param bool re_download: 是否重新下载数据,以重新切分数据。 - :return: str + :param dev_ratio: 如果路径中没有验证集,从 train 划分多少作为 dev 的数据。 如果为 **0** ,则不划分 dev + :param re_download: 是否重新下载数据,以重新切分数据。 + :return: 数据集的目录地址 """ if self.dataset_name is None: return '' diff --git a/fastNLP/io/loader/json.py b/fastNLP/io/loader/json.py index e5648a26..31dfce9d 100644 --- a/fastNLP/io/loader/json.py +++ b/fastNLP/io/loader/json.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "JsonLoader" ] @@ -11,19 +9,16 @@ from fastNLP.core.dataset import DataSet, Instance class JsonLoader(Loader): r""" - 别名::class:`fastNLP.io.JsonLoader` :class:`fastNLP.io.loader.JsonLoader` - - 读取json格式数据.数据必须按行存储,每行是一个包含各类属性的json对象 + 读取 *json* 格式数据,数据必须按行存储,每行是一个包含各类属性的 json 对象。 - :param dict fields: 需要读入的json属性名称, 和读入后在DataSet中存储的field_name - ``fields`` 的 `key` 必须是json对象的属性名. ``fields`` 的 `value` 为读入后在DataSet存储的 `field_name` , - `value` 也可为 ``None`` , 这时读入后的 `field_name` 与json对象对应属性同名 - ``fields`` 可为 ``None`` , 这时,json对象所有属性都保存在DataSet中. Default: ``None`` - :param bool dropna: 是否忽略非法数据,若 ``True`` 则忽略,若 ``False`` ,在遇到非法数据时,抛出 ``ValueError`` . - Default: ``False`` + :param fields: 需要读入的 json 属性名称,和读入后在 :class:`~fastNLP.core.DataSet` 中存储的 `field_name`。 + ``fields`` 的 `key` 必须是 json 对象的 **属性名**, ``fields`` 的 `value` 为读入后在 ``DataSet`` 存储的 `field_name` , + `value` 也可为 ``None`` ,这时读入后的 `field_name` 与 json 对象对应属性同名。 + ``fields`` 可为 ``None`` ,这时 json 对象所有属性都保存在 ``DataSet`` 中。 + :param dropna: 是否忽略非法数据,若为 ``True`` 则忽略;若为 ``False`` 则在遇到非法数据时抛出 :class:`ValueError`。 """ - def __init__(self, fields=None, dropna=False): + def __init__(self, fields: dict=None, dropna=False): super(JsonLoader, self).__init__() self.dropna = dropna self.fields = None diff --git a/fastNLP/io/loader/loader.py b/fastNLP/io/loader/loader.py index 135a9d74..2294f476 100644 --- a/fastNLP/io/loader/loader.py +++ b/fastNLP/io/loader/loader.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "Loader" ] @@ -14,24 +12,23 @@ from fastNLP.core.dataset import DataSet class Loader: r""" - 各种数据 Loader 的基类,提供了 API 的参考. - Loader支持以下的三个函数 + 各种数据 **Loader** 的基类,提供了 API 的参考。 + :class:`Loader` 支持以下的三个函数 - - download() 函数:自动将该数据集下载到缓存地址,默认缓存地址为~/.fastNLP/datasets/。由于版权等原因,不是所有的Loader都实现了该方法。该方法会返回下载后文件所处的缓存地址。 - - _load() 函数:从一个数据文件中读取数据,返回一个 :class:`~fastNLP.DataSet` 。返回的DataSet的内容可以通过每个Loader的文档判断出。 - - load() 函数:将文件分别读取为DataSet,然后将多个DataSet放入到一个DataBundle中并返回 - + - :meth:`download` 函数:自动将该数据集下载到缓存地址,默认缓存地址为 ``~/.fastNLP/datasets/`` 。由于版权等原因,不是所有的 ``Loader`` 都实现了该方法。 + 该方法会返回下载后文件所处的缓存地址。 + - :meth:`_load` 函数:从一个数据文件中读取数据,返回一个 :class:`~fastNLP.core.DataSet` 。返回的 DataSet 的内容可以通过每个 ``Loader`` 的文档判断出。 + - :meth:`load` 函数:将文件分别读取为 :class:`~fastNLP.core.DataSet` ,然后将多个 DataSet 放入到一个 :class:`~fastNLP.io.DataBundle` 中并返回 """ - def __init__(self): pass def _load(self, path: str) -> DataSet: r""" - 给定一个路径,返回读取的DataSet。 + 给定一个路径,返回读取的 :class:`~fastNLP.core.DataSet` 。 - :param str path: 路径 - :return: DataSet + :param path: 路径 + :return: :class:`~fastNLP.core.DataSet` """ raise NotImplementedError @@ -39,29 +36,29 @@ class Loader: r""" 从指定一个或多个路径中的文件中读取数据,返回 :class:`~fastNLP.io.DataBundle` 。 - :param Union[str, Dict[str, str]] paths: 支持以下的几种输入方式: - - 0.如果为None,则先查看本地是否有缓存,如果没有则自动下载并缓存。 + :param paths: 支持以下的几种输入方式: - 1.传入一个目录, 该目录下名称包含train的被认为是train,包含test的被认为是test,包含dev的被认为是dev,如果检测到多个文件名包含'train'、 'dev'、 'test'则会报错:: + - ``None`` -- 先查看本地是否有缓存,如果没有则自动下载并缓存。 + - 一个目录,该目录下名称包含 ``'train'`` 的被认为是训练集,包含 ``'test'`` 的被认为是测试集,包含 ``'dev'`` 的被认为是验证集 / 开发集, + 如果检测到多个文件名包含 ``'train'``、 ``'dev'``、 ``'test'`` 则会报错:: data_bundle = xxxLoader().load('/path/to/dir') # 返回的DataBundle中datasets根据目录下是否检测到train - # dev、 test等有所变化,可以通过以下的方式取出DataSet + # dev、 test 等有所变化,可以通过以下的方式取出 DataSet tr_data = data_bundle.get_dataset('train') te_data = data_bundle.get_dataset('test') # 如果目录下有文件包含test这个字段 - 2.传入一个dict,比如train,dev,test不在同一个目录下,或者名称中不包含train, dev, test:: + - 传入一个 :class:`dict` ,比如训练集、验证集和测试集不在同一个目录下,或者名称中不包含 ``'train'``、 ``'dev'``、 ``'test'`` :: paths = {'train':"/path/to/tr.conll", 'dev':"/to/validate.conll", "test":"/to/te.conll"} data_bundle = xxxLoader().load(paths) # 返回的DataBundle中的dataset中包含"train", "dev", "test" dev_data = data_bundle.get_dataset('dev') - 3.传入文件路径:: + - 传入文件路径:: data_bundle = xxxLoader().load("/path/to/a/train.conll") # 返回DataBundle对象, datasets中仅包含'train' tr_data = data_bundle.get_dataset('train') # 取出DataSet - :return: 返回的 :class:`~fastNLP.io.DataBundle` + :return: :class:`~fastNLP.io.DataBundle` """ if paths is None: paths = self.download() diff --git a/fastNLP/io/loader/matching.py b/fastNLP/io/loader/matching.py index ed5c84c0..27689a18 100644 --- a/fastNLP/io/loader/matching.py +++ b/fastNLP/io/loader/matching.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "MNLILoader", "SNLILoader", @@ -26,17 +24,19 @@ from fastNLP.core.log import logger class MNLILoader(Loader): r""" - 读取的数据格式为: + **MNLI** 数据集的 **Loader**,如果您使用了这个数据,请引用 - Example:: + https://www.nyu.edu/projects/bowman/multinli/paper.pdf + + 读取的数据格式为:: index promptID pairID genre sentence1_binary_parse sentence2_binary_parse sentence1_parse sentence2_parse sentence1 sentence2 label1 gold_label 0 31193 31193n government ( ( Conceptually ( cream skimming ) ) ... 1 101457 101457e telephone ( you ( ( know ( during ( ( ( the season ) and ) ( i guess ) ) )... ... - 读取MNLI任务的数据,读取之后的DataSet中包含以下的内容,words0是sentence1, words1是sentence2, target是gold_label, 测试集中没 - 有target列。 + 读取之后的 :class:`~fastNLP.core.DataSet` 中包含以下的内容: ``raw_words`` 是 ``sentence1`` , ``raw_words2`` 是 ``sentence2`` , + ``target`` 是 ``gold_label``。测试集中没有 ``target`` 列。 .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -80,10 +80,9 @@ class MNLILoader(Loader): def load(self, paths: str = None): r""" - - :param str paths: 传入数据所在目录,会在该目录下寻找dev_matched.tsv, dev_mismatched.tsv, test_matched.tsv, - test_mismatched.tsv, train.tsv文件夹 - :return: DataBundle + :param paths: 传入数据所在目录,会在该目录下寻找 ``dev_matched.tsv``, ``dev_mismatched.tsv``, ``test_matched.tsv``, + ``test_mismatched.tsv``, ``train.tsv`` 文件。 + :return: :class:`~fastNLP.io.DataBundle` """ if paths: paths = os.path.abspath(os.path.expanduser(paths)) @@ -112,10 +111,9 @@ class MNLILoader(Loader): def download(self): r""" - 如果你使用了这个数据,请引用 + 自动下载数据集。 - https://www.nyu.edu/projects/bowman/multinli/paper.pdf - :return: + :return: 数据集目录地址 """ output_dir = self._get_dataset_path('mnli') return output_dir @@ -123,9 +121,11 @@ class MNLILoader(Loader): class SNLILoader(JsonLoader): r""" - 文件每一行是一个sample,每一行都为一个json对象,其数据格式为: + **SNLI** 数据集的 **Loader**,如果您的文章使用了这份数据,请引用 - Example:: + http://nlp.stanford.edu/pubs/snli_paper.pdf + + 文件每一行是一个 sample,每一行都为一个 ``json`` 对象,其数据格式为:: {"annotator_labels": ["neutral", "entailment", "neutral", "neutral", "neutral"], "captionID": "4705552913.jpg#2", "gold_label": "neutral", "pairID": "4705552913.jpg#2r1n", @@ -137,7 +137,7 @@ class SNLILoader(JsonLoader): "sentence2_parse": "(ROOT (S (NP (DT The) (NNS sisters)) (VP (VBP are) (VP (VBG hugging) (NP (UH goodbye)) (PP (IN while) (S (VP (VBG holding) (S (VP (TO to) (VP (VB go) (NP (NNS packages)) (PP (IN after) (S (ADVP (RB just)) (VP (VBG eating) (NP (NN lunch))))))))))))) (. .)))" } - 读取之后的DataSet中的field情况为 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: 下面是使用SNLILoader加载的DataSet所具备的field :header: "target", "raw_words1", "raw_words2", @@ -158,13 +158,11 @@ class SNLILoader(JsonLoader): def load(self, paths: Union[str, Dict[str, str]] = None) -> DataBundle: r""" 从指定一个或多个路径中的文件中读取数据,返回 :class:`~fastNLP.io.DataBundle` 。 + 读取的 field 根据 :class:`SNLILoader` 初始化时传入的 ``fields`` 决定。 - 读取的field根据Loader初始化时传入的field决定。 - - :param str paths: 传入一个目录, 将在该目录下寻找snli_1.0_train.jsonl, snli_1.0_dev.jsonl - 和snli_1.0_test.jsonl三个文件。 - - :return: :class:`~fastNLP.io.DataBundle` + :param str paths: 传入一个目录, 将在该目录下寻找 ``snli_1.0_train.jsonl``, ``snli_1.0_dev.jsonl`` + 和 ``snli_1.0_test.jsonl`` 三个文件。 + :return: """ _paths = {} if paths is None: @@ -187,26 +185,26 @@ class SNLILoader(JsonLoader): def download(self): r""" - 如果您的文章使用了这份数据,请引用 - - http://nlp.stanford.edu/pubs/snli_paper.pdf + 自动下载数据集。 - :return: str + :return: 数据集目录地址 """ return self._get_dataset_path('snli') class QNLILoader(JsonLoader): r""" - 第一行为标题(具体内容会被忽略),之后每一行是一个sample,由index、问题、句子和标签构成(以制表符分割),数据结构如下: + **QNLI** 数据集的 **Loader** ,如果您的实验使用到了该数据,请引用 - Example:: + https://arxiv.org/pdf/1809.05053.pdf + + 读取数据的格式为:第一行为标题(具体内容会被忽略),之后每一行是一个 sample,由 **index** 、**问题** 、**句子** 和 **标签** 构成(以制表符分割),数据结构如下:: index question sentence label 0 What came into force after the new constitution was herald? As of that day, the new constitution heralding the Second Republic came into force. entailment - QNLI数据集的Loader, - 加载的DataSet将具备以下的field, raw_words1是question, raw_words2是sentence, target是label + 加载的 :class:`~fastNLP.core.DataSet` 将具备以下的内容: ``raw_words1`` 是 ``question`` , ``raw_words2`` 是 ``sentence`` , ``target`` 是 ``label`` 。 + 测试集中没有 ``target`` 列。 .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -214,8 +212,6 @@ class QNLILoader(JsonLoader): "What came into force after the new...", "As of that day...", "entailment" "...","." - test数据集没有target列 - """ def __init__(self): @@ -250,26 +246,27 @@ class QNLILoader(JsonLoader): def download(self): r""" - 如果您的实验使用到了该数据,请引用 + 自动下载数据集。 - https://arxiv.org/pdf/1809.05053.pdf - - :return: + :return: 数据集目录地址 """ return self._get_dataset_path('qnli') class RTELoader(Loader): r""" - 第一行为标题(具体内容会被忽略),之后每一行是一个sample,由index、句子1、句子2和标签构成(以制表符分割),数据结构如下: + **RTE** 数据集的 **Loader**,如果您使用了该数据,请引用 **GLUE Benchmark** : - Example:: + https://openreview.net/pdf?id=rJ4km2R5t7 + + 读取数据的格式为:第一行为标题(具体内容会被忽略),之后每一行是一个 sample,由 **index** 、**句子1** 、**句子2** 和 **标签** + 构成(以制表符分割),数据结构如下:: index sentence1 sentence2 label 0 Dana Reeve, the widow of the actor Christopher Reeve, has died of lung cancer at age 44, according to the Christopher Reeve Foundation. Christopher Reeve had an accident. not_entailment - RTE数据的loader - 加载的DataSet将具备以下的field, raw_words1是sentence0,raw_words2是sentence1, target是label + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的内容:``raw_words1`` 是 ``sentence1`` , ``raw_words2`` 是 ``sentence2`` , ``target`` 是 ``label`` 。 + 测试集中没有 ``target`` 列。 .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -277,7 +274,6 @@ class RTELoader(Loader): "Dana Reeve, the widow of the actor...", "Christopher Reeve had an...", "not_entailment" "...","..." - test数据集没有target列 """ def __init__(self): @@ -312,20 +308,17 @@ class RTELoader(Loader): def download(self): r""" - 如果您的实验使用到了该数据,请引用GLUE Benchmark + 自动下载数据集。 - https://openreview.net/pdf?id=rJ4km2R5t7 - - :return: + :return: 数据集目录地址 """ return self._get_dataset_path('rte') class QuoraLoader(Loader): r""" - Quora matching任务的数据集Loader - - 支持读取的文件中的内容,应该有以下的形式, 以制表符分隔,且前三列的内容必须是:第一列是label,第二列和第三列是句子 + **Quora matching** 任务的数据集 **Loader**。 + 支持读取的文件中的内容应该有以下的形式:以制表符分隔,且前三列一定分别为 **label** , **句子1** , **句子2** 。 Example:: @@ -333,7 +326,7 @@ class QuoraLoader(Loader): 0 Is honey a viable alternative to sugar for diabetics ? How would you compare the United States ' euthanasia laws to Denmark ? 90348 ... - 加载的DataSet将具备以下的field + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -370,21 +363,27 @@ class QuoraLoader(Loader): :return: """ + r""" + 自动下载数据集。 + + :return: 数据集目录地址 + """ raise RuntimeError("Quora cannot be downloaded automatically.") class CNXNLILoader(Loader): r""" - 数据集简介:中文句对NLI(本为multi-lingual的数据集,但是这里只取了中文的数据集)。原句子已被MOSES tokenizer处理,这里我们将其还原并重新按字tokenize - 原始数据数据为: - - Example:: + **XNLI Chinese** 数据集的 **Loader** ,该数据取自 https://arxiv.org/abs/1809.05053 ,在 https://arxiv.org/pdf/1905.05526.pdf + 、 https://arxiv.org/pdf/1901.10125.pdf 和 https://arxiv.org/pdf/1809.05053.pdf 有使用。 + + 该数据集为中文句对 NLI(本为 ``multi-lingual`` 的数据集,但是这里只取了中文的数据集)。原句子已被 + ``MOSES tokenizer`` 处理,这里我们将其还原并重新按字 tokenize 。原始数据为:: premise hypo label 我们 家里 有 一个 但 我 没 找到 我 可以 用 的 时间 我们 家里 有 一个 但 我 从来 没有 时间 使用 它 . entailment - dev和test中的数据为csv或json格式,包括十多个field,这里只取与以上三个field中的数据 - 读取后的Dataset将具有以下数据结构: + 验证集和测试集中的数据为 csv 或 json 格式,这里只取以上三个 field 中的数据。 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars1", "raw_chars2", "target" @@ -444,6 +443,13 @@ class CNXNLILoader(Loader): return ds def load(self, paths: Union[str, Dict[str, str]] = None) -> DataBundle: + """ + 从指定一个或多个路径中的文件中读取数据,返回 :class:`~fastNLP.io.DataBundle` 。 + 读取的 field 根据 :class:`SNLILoader` 初始化时传入的 ``fields`` 决定。 + + :param paths: + :return: + """ if paths is None: paths = self.download() paths = check_loader_paths(paths) @@ -459,10 +465,9 @@ class CNXNLILoader(Loader): def download(self) -> str: r""" - 自动下载数据,该数据取自 https://arxiv.org/abs/1809.05053 - 在 https://arxiv.org/pdf/1905.05526.pdf https://arxiv.org/pdf/1901.10125.pdf - https://arxiv.org/pdf/1809.05053.pdf 有使用 - :return: + 自动下载数据集。 + + :return: 数据集目录地址 """ output_dir = self._get_dataset_path('cn-xnli') return output_dir @@ -470,23 +475,19 @@ class CNXNLILoader(Loader): class BQCorpusLoader(Loader): r""" - 别名: - 数据集简介:句子对二分类任务(判断是否具有相同的语义) - 原始数据结构为: - - Example:: + **BQ Corpus** 数据集的 **Loader** 。句子对二分类任务,判断是否具有相同的语义。原始数据结构为:: sentence1,sentence2,label 综合评分不足什么原因,综合评估的依据,0 - 什么时候我能使用微粒贷,你就赶快给我开通就行了,0 + 什么时候我能使用微粒贷,您就赶快给我开通就行了,0 - 读取后的Dataset将具有以下数据结构: + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars1", "raw_chars2", "target" "综合评分不足什么原因", "综合评估的依据", "0" - "什么时候我能使用微粒贷", "你就赶快给我开通就行了", "0" + "什么时候我能使用微粒贷", "您就赶快给我开通就行了", "0" "...", "...", "..." """ @@ -514,31 +515,25 @@ class BQCorpusLoader(Loader): 由于版权限制,不能提供自动下载功能。可参考 https://github.com/ymcui/Chinese-BERT-wwm - - :return: """ raise RuntimeError("BQCorpus cannot be downloaded automatically.") class LCQMCLoader(Loader): r""" - 数据集简介:句对匹配(question matching) - - 原始数据为: - - Example:: + **LCQMC** 数据集的 **Loader**,该数据集用于句对匹配(question matching)。原始数据为:: 喜欢打篮球的男生喜欢什么样的女生 爱打篮球的男生喜欢什么样的女生 1 - 你帮我设计小说的封面吧 谁能帮我给小说设计个封面? 0 + 您帮我设计小说的封面吧 谁能帮我给小说设计个封面? 0 - 读取后的Dataset将具有以下的数据结构 + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: .. csv-table:: :header: "raw_chars1", "raw_chars2", "target" "喜欢打篮球的男生喜欢什么样的女生", "爱打篮球的男生喜欢什么样的女生", "1" - "你帮我设计小说的封面吧", "妇可以戴耳机听音乐吗?", "0" + "您帮我设计小说的封面吧", "妇可以戴耳机听音乐吗?", "0" "...", "...", "..." @@ -569,8 +564,6 @@ class LCQMCLoader(Loader): 由于版权限制,不能提供自动下载功能。可参考 https://github.com/ymcui/Chinese-BERT-wwm - - :return: """ raise RuntimeError("LCQMC cannot be downloaded automatically.") diff --git a/fastNLP/io/loader/qa.py b/fastNLP/io/loader/qa.py index a3140b01..b6329daf 100644 --- a/fastNLP/io/loader/qa.py +++ b/fastNLP/io/loader/qa.py @@ -1,6 +1,5 @@ r""" -该文件中的Loader主要用于读取问答式任务的数据 - +该文件中的 **Loader** 主要用于读取问答式任务的数据 """ @@ -13,20 +12,23 @@ __all__ = ['CMRC2018Loader'] class CMRC2018Loader(Loader): r""" - 请直接使用从fastNLP下载的数据进行处理。该数据集未提供测试集,测试需要通过上传到对应的系统进行评测 + **CMRC2018** 数据集的 **Loader** ,如果您使用了本数据,请引用 + A Span-Extraction Dataset for Chinese Machine Reading Comprehension. Yiming Cui, Ting Liu, etc. + + 请直接使用从 **fastNLP** 下载的数据进行处理。该数据集未提供测试集,测试需要通过上传到对应的系统进行评测。 - 读取之后训练集DataSet将具备以下的内容,每个问题的答案只有一个 + 读取之后训练集 :class:`~fastNLP.core.DataSet` 将具备以下的内容,每个问题的答案只有一个: .. csv-table:: - :header:"title", "context", "question", "answers", "answer_starts", "id" + :header: "title", "context", "question", "answers", "answer_starts", "id" "范廷颂", "范廷颂枢机(,),圣名保禄·若瑟()...", "范廷颂是什么时候被任为主教的?", ["1963年"], ["30"], "TRAIN_186_QUERY_0" "范廷颂", "范廷颂枢机(,),圣名保禄·若瑟()...", "1990年,范廷颂担任什么职务?", ["1990年被擢升为天..."], ["41"],"TRAIN_186_QUERY_1" "...", "...", "...","...", ".", "..." - 其中title是文本的标题,多条记录可能是相同的title;id是该问题的id,具备唯一性 + 其中 ``title`` 是文本的标题,多条记录可能是相同的 ``title`` ;``id`` 是该问题的 id,具备唯一性。 - 验证集DataSet将具备以下的内容,每个问题的答案可能有三个(有时候只是3个重复的答案) + 验证集 :class:`~fastNLP.core.DataSet` 将具备以下的内容,每个问题的答案可能有三个(有时候只是3个重复的答案): .. csv-table:: :header: "title", "context", "question", "answers", "answer_starts", "id" @@ -35,8 +37,8 @@ class CMRC2018Loader(Loader): "战国无双3", "《战国无双3》()是由光荣和ω-force开发...", "男女主角亦有专属声优这一模式是由谁改编的?", "['村雨城', '村雨城', '任天堂游戏谜之村雨城']", "[226, 226, 219]", "DEV_0_QUERY_1" "...", "...", "...","...", ".", "..." - 其中answer_starts是从0开始的index。例如"我来自a复旦大学?",其中"复"的开始index为4。另外"Russell评价说"中的说的index为9, 因为 - 英文和数字都直接按照character计量的。 + 其中 ``answer_starts`` 是从 0 开始的 index。例如 ``"我来自a复旦大学?"`` ,其中 ``"复"`` 的开始 index 为 **4**。另外 ``"Russell评价说"`` + 中的 ``"说"`` 的 index 为 **9** , 因为英文和数字都直接按照 character 计量的。 """ def __init__(self): super().__init__() @@ -65,9 +67,9 @@ class CMRC2018Loader(Loader): def download(self) -> str: r""" - 如果您使用了本数据,请引用A Span-Extraction Dataset for Chinese Machine Reading Comprehension. Yiming Cui, Ting Liu, etc. + 自动下载数据集。 - :return: + :return: 数据集目录地址 """ output_dir = self._get_dataset_path('cmrc2018') return output_dir diff --git a/fastNLP/io/loader/summarization.py b/fastNLP/io/loader/summarization.py new file mode 100644 index 00000000..6dcb755f --- /dev/null +++ b/fastNLP/io/loader/summarization.py @@ -0,0 +1,64 @@ +__all__ = [ + "ExtCNNDMLoader" +] + +import os +from typing import Union, Dict + +from ..data_bundle import DataBundle +from ..utils import check_loader_paths +from .json import JsonLoader + + +class ExtCNNDMLoader(JsonLoader): + r""" + **CNN / Daily Mail** 数据集的 **Loader** ,用于 **extractive summarization task** 任务。 + 如果你使用了这个数据,请引用 https://arxiv.org/pdf/1506.03340.pdf + + 读取的 :class:`~fastNLP.core.DataSet` 将具备以下的数据结构: + + .. csv-table:: + :header: "text", "summary", "label", "publication" + + "['I got new tires from them and... ','...']", "['The new tires...','...']", "[0, 1]", "cnndm" + "['Don't waste your time. We had two...','...']", "['Time is precious','...']", "[1]", "cnndm" + "['...']", "['...']", "[]", "cnndm" + + :param fields: + """ + + def __init__(self, fields=None): + fields = fields or {"text": None, "summary": None, "label": None, "publication": None} + super(ExtCNNDMLoader, self).__init__(fields=fields) + + def load(self, paths: Union[str, Dict[str, str]] = None): + r""" + 从指定一个或多个路径中的文件中读取数据,返回 :class:`~fastNLP.io.DataBundle` 。 + + 读取的 field 根据 :class:`ExtCNNDMLoader` 初始化时传入的 ``fields`` 决定。 + + :param paths: 传入一个目录, 将在该目录下寻找 ``train.label.jsonl`` , ``dev.label.jsonl`` , + ``test.label.jsonl`` 三个文件(该目录还应该需要有一个名字为 ``vocab`` 的文件,在 :class:`~fastNLP.io.pipe.ExtCNNDMPipe` + 当中需要用到)。 + + :return: :class:`~fastNLP.io.DataBundle` + """ + if paths is None: + paths = self.download() + paths = check_loader_paths(paths) + if ('train' in paths) and ('test' not in paths): + paths['test'] = paths['train'] + paths.pop('train') + + datasets = {name: self._load(path) for name, path in paths.items()} + data_bundle = DataBundle(datasets=datasets) + return data_bundle + + def download(self): + r""" + 自动下载数据集。 + + :return: 数据集目录地址 + """ + output_dir = self._get_dataset_path('ext-cnndm') + return output_dir diff --git a/fastNLP/io/pipe/classification.py b/fastNLP/io/pipe/classification.py index a29de173..54df7d00 100644 --- a/fastNLP/io/pipe/classification.py +++ b/fastNLP/io/pipe/classification.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "CLSBasePipe", "AGsNewsPipe", @@ -36,8 +34,17 @@ from fastNLP.core.log import logger class CLSBasePipe(Pipe): + """ + 处理分类数据集 **Pipe** 的基类。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw', 'cn-char']`` 。``'raw'`` 表示使用空格作为切分, ``'cn-char'`` 表示 + 按字符切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param lang: :mod:`spacy` 使用的语言,当前仅支持 ``'en'`` 。 + :param num_proc: 处理数据时使用的进程数目。 + """ - def __init__(self, lower: bool = False, tokenizer: str = 'raw', lang='en', num_proc=0): + def __init__(self, lower: bool = False, tokenizer: str = 'raw', lang: str='en', num_proc: int=0): super().__init__() self.lower = lower self.tokenizer = get_tokenizer(tokenizer, lang=lang) @@ -61,7 +68,7 @@ class CLSBasePipe(Pipe): def process(self, data_bundle: DataBundle): r""" - 传入的DataSet应该具备如下的结构 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构: .. csv-table:: :header: "raw_words", "target" @@ -71,7 +78,7 @@ class CLSBasePipe(Pipe): "...", "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ # 复制一列words data_bundle = _add_words_field(data_bundle, lower=self.lower) @@ -87,46 +94,32 @@ class CLSBasePipe(Pipe): def process_from_file(self, paths) -> DataBundle: r""" - 传入文件路径,生成处理好的DataBundle对象。paths支持的路径形式可以参考 ::meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` :param paths: - :return: DataBundle + :return: """ raise NotImplementedError class YelpFullPipe(CLSBasePipe): r""" - 处理YelpFull的数据, 处理之后DataSet中的内容如下 + 处理 **Yelp Review Full** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: - .. csv-table:: 下面是使用YelpFullPipe处理后的DataSet所具备的field + .. csv-table:: 下面是使用 YelpFullPipe 处理后的 DataSet 所具备的 field :header: "raw_words", "target", "words", "seq_len" "I got 'new' tires from them and within...", 0 ,"[7, 110, 22, 107, 22, 499, 59, 140, 3,...]", 160 " Don't waste your time. We had two dif... ", 0, "[277, 17, 278, 38, 30, 112, 24, 85, 27...", 40 "...", ., "[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param lower: 是否对输入进行小写化。 + :param granularity: 支持 ``[2, 3, 5]`` 。若为 ``2`` ,则认为是二分类问题,将 **1、2** 归为一类, **4、5** 归为一类, + 丢掉 3;若为 ``3`` ,则认为是三分类问题,将 **1、2** 归为一类, **3** 归为一类, **4、5** 归为一类;若为 ``5`` ,则认为是五分类问题。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ - - def __init__(self, lower: bool = False, granularity=5, tokenizer: str = 'spacy', num_proc=0): - r""" - - :param bool lower: 是否对输入进行小写化。 - :param int granularity: 支持2, 3, 5。若为2, 则认为是2分类问题,将1、2归为1类,4、5归为一类,丢掉2;若为3, 则有3分类问题,将 - 1、2归为1类,3归为1类,4、5归为1类;若为5, 则有5分类问题。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。支持'spacy'和'raw'。raw使用空格作为切分。 - """ + def __init__(self, lower: bool = False, granularity: int=5, tokenizer: str = 'spacy', num_proc: int=0): super().__init__(lower=lower, tokenizer=tokenizer, lang='en', num_proc=num_proc) assert granularity in (2, 3, 5), "granularity can only be 2,3,5." self.granularity = granularity @@ -140,7 +133,7 @@ class YelpFullPipe(CLSBasePipe): def process(self, data_bundle): r""" - 传入的DataSet应该具备如下的结构 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构: .. csv-table:: :header: "raw_words", "target" @@ -150,7 +143,7 @@ class YelpFullPipe(CLSBasePipe): "...", "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ if self.tag_map is not None: data_bundle = _granularize(data_bundle, self.tag_map) @@ -159,11 +152,12 @@ class YelpFullPipe(CLSBasePipe): return data_bundle - def process_from_file(self, paths=None): + def process_from_file(self, paths=None) -> DataBundle: r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` :param paths: - :return: DataBundle + :return: """ data_bundle = YelpFullLoader().load(paths) return self.process(data_bundle=data_bundle) @@ -171,7 +165,7 @@ class YelpFullPipe(CLSBasePipe): class YelpPolarityPipe(CLSBasePipe): r""" - 处理YelpPolarity的数据, 处理之后DataSet中的内容如下 + 处理 **Yelp Review Polarity** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: 下面是使用YelpFullPipe处理后的DataSet所具备的field :header: "raw_words", "target", "words", "seq_len" @@ -180,32 +174,20 @@ class YelpPolarityPipe(CLSBasePipe): " Don't waste your time. We had two dif... ", 0, "[277, 17, 278, 38, 30, 112, 24, 85, 27...", 40 "...", ., "[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): - r""" - - :param bool lower: 是否对输入进行小写化。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。支持'spacy'和'raw'。raw使用空格作为切分。 - """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int=0): super().__init__(lower=lower, tokenizer=tokenizer, lang='en', num_proc=num_proc) def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param str paths: - :return: DataBundle + :param paths: + :return: """ data_bundle = YelpPolarityLoader().load(paths) return self.process(data_bundle=data_bundle) @@ -213,7 +195,7 @@ class YelpPolarityPipe(CLSBasePipe): class AGsNewsPipe(CLSBasePipe): r""" - 处理AG's News的数据, 处理之后DataSet中的内容如下 + 处理 **AG's News** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: 下面是使用AGsNewsPipe处理后的DataSet所具备的field :header: "raw_words", "target", "words", "seq_len" @@ -222,31 +204,20 @@ class AGsNewsPipe(CLSBasePipe): " Don't waste your time. We had two dif... ", 0, "[277, 17, 278, 38, 30, 112, 24, 85, 27...", 40 "...", ., "[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): - r""" - - :param bool lower: 是否对输入进行小写化。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。支持'spacy'和'raw'。raw使用空格作为切分。 - """ super().__init__(lower=lower, tokenizer=tokenizer, lang='en', num_proc=num_proc) def process_from_file(self, paths=None): r""" - :param str paths: - :return: DataBundle + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: """ data_bundle = AGsNewsLoader().load(paths) return self.process(data_bundle=data_bundle) @@ -254,7 +225,7 @@ class AGsNewsPipe(CLSBasePipe): class DBPediaPipe(CLSBasePipe): r""" - 处理DBPedia的数据, 处理之后DataSet中的内容如下 + 处理 **DBPedia** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: 下面是使用DBPediaPipe处理后的DataSet所具备的field :header: "raw_words", "target", "words", "seq_len" @@ -263,31 +234,20 @@ class DBPediaPipe(CLSBasePipe): " Don't waste your time. We had two dif... ", 0, "[277, 17, 278, 38, 30, 112, 24, 85, 27...", 40 "...", ., "[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): - r""" - - :param bool lower: 是否对输入进行小写化。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。支持'spacy'和'raw'。raw使用空格作为切分。 - """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int=0): super().__init__(lower=lower, tokenizer=tokenizer, lang='en', num_proc=num_proc) def process_from_file(self, paths=None): r""" - :param str paths: - :return: DataBundle + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: """ data_bundle = DBPediaLoader().load(paths) return self.process(data_bundle=data_bundle) @@ -295,7 +255,7 @@ class DBPediaPipe(CLSBasePipe): class SSTPipe(CLSBasePipe): r""" - 经过该Pipe之后,DataSet中具备的field如下所示 + 处理 **SST** 的数据,处理之后, :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: 下面是使用SSTPipe处理后的DataSet所具备的field :header: "raw_words", "words", "target", "seq_len" @@ -304,29 +264,15 @@ class SSTPipe(CLSBasePipe): "No one goes unindicted here , which is...", 0, "[191, 126, 192, 193, 194, 4, 195, 17, ...", 13 "...", ., "[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param subtree: 是否将训练集、测试集和验证集数据展开为子树,扩充数据量。 + :param train_subtree: 是否将训练集通过子树扩展数据。 + :param lower: 是否对输入进行小写化。 + :param granularity: 支持 ``[2, 3, 5]`` 。若为 ``2`` ,则认为是二分类问题,将 **1、2** 归为一类, **4、5** 归为一类, + 丢掉 3;若为 ``3`` ,则认为是三分类问题,将 **1、2** 归为一类, **3** 归为一类, **4、5** 归为一类;若为 ``5`` ,则认为是五分类问题。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ - - def __init__(self, subtree=False, train_subtree=True, lower=False, granularity=5, tokenizer='spacy', num_proc=0): - r""" - - :param bool subtree: 是否将train, test, dev数据展开为子树,扩充数据量。 Default: ``False`` - :param bool train_subtree: 是否将train集通过子树扩展数据。 - :param bool lower: 是否对输入进行小写化。 - :param int granularity: 支持2, 3, 5。若为2, 则认为是2分类问题,将0、1归为1类,3、4归为一类,丢掉2;若为3, 则有3分类问题,将 - 0、1归为1类,2归为1类,3、4归为1类;若为5, 则有5分类问题。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。支持'spacy'和'raw'。raw使用空格作为切分。 - """ + def __init__(self, subtree: bool=False, train_subtree: bool=True, lower: bool=False, granularity: int=5, tokenizer: int='spacy', num_proc: int=0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.subtree = subtree self.train_tree = train_subtree @@ -341,19 +287,19 @@ class SSTPipe(CLSBasePipe): else: self.tag_map = None - def process(self, data_bundle: DataBundle): + def process(self, data_bundle: DataBundle) -> DataBundle: r""" - 对DataBundle中的数据进行预处理。输入的DataSet应该至少拥有raw_words这一列,且内容类似与 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` ` 应该至少拥有 ``raw_words`` 列,内容类似于: - .. csv-table:: 下面是使用SSTLoader读取的DataSet所具备的field + .. csv-table:: 下面是使用 SSTLoader 读取的 DataSet 所具备的 field :header: "raw_words" "(2 (3 (3 Effective) (2 but)) (1 (1 too-tepid)..." "(3 (3 (2 If) (3 (2 you) (3 (2 sometimes) ..." "..." - :param ~fastNLP.io.DataBundle data_bundle: 需要处理的DataBundle对象 - :return: + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象 + :return: 处理后的 ``data_bundle`` """ # 先取出subtree for name in list(data_bundle.datasets.keys()): @@ -381,13 +327,19 @@ class SSTPipe(CLSBasePipe): return data_bundle def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = SSTLoader().load(paths) return self.process(data_bundle=data_bundle) class SST2Pipe(CLSBasePipe): r""" - 加载SST2的数据, 处理完成之后DataSet将拥有以下的field + 处理 **SST-2** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words", "target", "words", "seq_len" @@ -396,32 +348,20 @@ class SST2Pipe(CLSBasePipe): "unflinchingly bleak and desperate", 0, "[115, 116, 5, 117]", 4 "...", "...", ., . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, lower=False, tokenizer='raw', num_proc=0): - r""" - - :param bool lower: 是否对输入进行小写化。 - :param str tokenizer: 使用哪种tokenize方式将数据切成单词。 - """ super().__init__(lower=lower, tokenizer=tokenizer, lang='en', num_proc=num_proc) def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param str paths: 如果为None,则自动下载并缓存到fastNLP的缓存地址。 - :return: DataBundle + :param paths: + :return: """ data_bundle = SST2Loader().load(paths) return self.process(data_bundle) @@ -429,43 +369,31 @@ class SST2Pipe(CLSBasePipe): class IMDBPipe(CLSBasePipe): r""" - 经过本Pipe处理后DataSet将如下 + 处理 **IMDb** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: - .. csv-table:: 输出DataSet的field + .. csv-table:: 输出 DataSet 的 field :header: "raw_words", "target", "words", "seq_len" "Bromwell High is a cartoon ... ", 0, "[3, 5, 6, 9, ...]", 20 "Story of a man who has ...", 1, "[20, 43, 9, 10, ...]", 31 "...", ., "[...]", . - 其中raw_words为str类型,是原文; words是转换为index的输入; target是转换为index的目标值; - words列被设置为input; target列被设置为target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | False | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ + 其中 ``raw_words`` 为 :class:`str` 类型,是原文; ``words`` 是转换为 index 的输入; ``target`` 是转换为 index 的目标值。 + ``words`` 列被设置为 input, ``target`` 列被设置为 target。 + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): - r""" - - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process(self, data_bundle: DataBundle): r""" - 期待的DataBunlde中输入的DataSet应该类似于如下,有两个field,raw_words和target,且均为str类型 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构:有两个 field , ``raw_words`` 和 ``target`` , + 且均为 :class:`str` 类型。 .. csv-table:: 输入DataSet的field :header: "raw_words", "target" @@ -476,7 +404,7 @@ class IMDBPipe(CLSBasePipe): :param DataBunlde data_bundle: 传入的DataBundle中的DataSet必须包含raw_words和target两个field,且raw_words列应该为str, target列应该为str。 - :return: DataBundle + :return: 处理后的 ``data_bundle`` """ # 替换
@@ -493,9 +421,10 @@ class IMDBPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = IMDBLoader().load(paths) @@ -506,7 +435,7 @@ class IMDBPipe(CLSBasePipe): class ChnSentiCorpPipe(Pipe): r""" - 处理之后的DataSet有以下的结构 + 处理 **ChnSentiCorp** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容为: .. csv-table:: :header: "raw_chars", "target", "chars", "seq_len" @@ -515,30 +444,18 @@ class ChnSentiCorpPipe(Pipe): "<荐书> 推荐所有喜欢<红楼>...", 1, "[10, 21, ....]", 25 "..." - 其中chars, seq_len是input,target是target - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ + 其中 ``chars`` , ``seq_len`` 是 input, ``target`` 是 target。 + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, bigrams=False, trigrams=False, num_proc: int = 0): - r""" - - :param bool bigrams: 是否增加一列bigrams. bigrams的构成是['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]。如果 - 设置为True,返回的DataSet将有一列名为bigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('bigrams')获取. - :param bool trigrams: 是否增加一列trigrams. trigrams的构成是 ['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...] - 。如果设置为True,返回的DataSet将有一列名为trigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('trigrams')获取. - """ + def __init__(self, bigrams: bool=False, trigrams: bool=False, num_proc: int = 0): super().__init__() self.bigrams = bigrams @@ -557,7 +474,7 @@ class ChnSentiCorpPipe(Pipe): def process(self, data_bundle: DataBundle): r""" - 可以处理的DataSet应该具备以下的field + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构: .. csv-table:: :header: "raw_chars", "target" @@ -567,7 +484,7 @@ class ChnSentiCorpPipe(Pipe): "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ _add_chars_field(data_bundle, lower=False) @@ -601,9 +518,10 @@ class ChnSentiCorpPipe(Pipe): def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = ChnSentiCorpLoader().load(paths) @@ -614,7 +532,7 @@ class ChnSentiCorpPipe(Pipe): class THUCNewsPipe(CLSBasePipe): r""" - 处理之后的DataSet有以下的结构 + 处理 **THUCNews** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容为: .. csv-table:: :header: "raw_chars", "target", "chars", "seq_len" @@ -622,27 +540,18 @@ class THUCNewsPipe(CLSBasePipe): "马晓旭意外受伤让国奥警惕 无奈大雨格外青睐殷家军记者傅亚雨沈阳报道...", 0, "[409, 1197, 2146, 213, ...]", 746 "..." - 其中chars, seq_len是input,target是target - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - - :param bool bigrams: 是否增加一列bigrams. bigrams的构成是['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]。如果 - 设置为True,返回的DataSet将有一列名为bigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('bigrams')获取. - :param bool trigrams: 是否增加一列trigrams. trigrams的构成是 ['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...] - 。如果设置为True,返回的DataSet将有一列名为trigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('trigrams')获取. + 其中 ``chars`` , ``seq_len`` 是 input, ``target`` 是target + + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, bigrams=False, trigrams=False, num_proc=0): + def __init__(self, bigrams: int=False, trigrams: int=False, num_proc: int=0): super().__init__(num_proc=num_proc) self.bigrams = bigrams @@ -663,7 +572,7 @@ class THUCNewsPipe(CLSBasePipe): def process(self, data_bundle: DataBundle): r""" - 可处理的DataSet应具备如下的field + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构: .. csv-table:: :header: "raw_words", "target" @@ -672,7 +581,7 @@ class THUCNewsPipe(CLSBasePipe): "...", "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ # 根据granularity设置tag tag_map = {'体育': 0, '财经': 1, '房产': 2, '家居': 3, '教育': 4, '科技': 5, '时尚': 6, '时政': 7, '游戏': 8, '娱乐': 9} @@ -713,8 +622,10 @@ class THUCNewsPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: """ data_loader = THUCNewsLoader() # 此处需要实例化一个data_loader,否则传入load()的参数为None data_bundle = data_loader.load(paths) @@ -724,32 +635,23 @@ class THUCNewsPipe(CLSBasePipe): class WeiboSenti100kPipe(CLSBasePipe): r""" - 处理之后的DataSet有以下的结构 + 处理 **WeiboSenti100k** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容为: .. csv-table:: :header: "raw_chars", "target", "chars", "seq_len" - "六一出生的?好讽刺…… //@祭春姬:他爸爸是外星人吧 //@面孔小高:现在的孩子都怎么了 [怒][怒][怒]", 0, "[0, 690, 18, ...]", 56 + "马晓旭意外受伤让国奥警惕 无奈大雨格外青睐殷家军记者傅亚雨沈阳报道...", 0, "[409, 1197, 2146, 213, ...]", 746 "..." - 其中chars, seq_len是input,target是target - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | False | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - - :param bool bigrams: 是否增加一列bigrams. bigrams的构成是['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]。如果 - 设置为True,返回的DataSet将有一列名为bigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('bigrams')获取. - :param bool trigrams: 是否增加一列trigrams. trigrams的构成是 ['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...] - 。如果设置为True,返回的DataSet将有一列名为trigrams, 且已经转换为了index并设置为input,对应的vocab可以通过 - data_bundle.get_vocab('trigrams')获取. + 其中 ``chars`` , ``seq_len`` 是 input, ``target`` 是target + + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 `~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, bigrams=False, trigrams=False, num_proc=0): @@ -770,7 +672,7 @@ class WeiboSenti100kPipe(CLSBasePipe): def process(self, data_bundle: DataBundle): r""" - 可处理的DataSet应具备以下的field + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备如下的结构: .. csv-table:: :header: "raw_chars", "target" @@ -779,7 +681,7 @@ class WeiboSenti100kPipe(CLSBasePipe): "...", "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ # clean,lower @@ -811,8 +713,10 @@ class WeiboSenti100kPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: """ data_loader = WeiboSenti100kLoader() # 此处需要实例化一个data_loader,否则传入load()的参数为None data_bundle = data_loader.load(paths) @@ -820,20 +724,23 @@ class WeiboSenti100kPipe(CLSBasePipe): return data_bundle class MRPipe(CLSBasePipe): - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): - r""" + """ + 加载 **MR** 的数据。 - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc=0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = MRLoader().load(paths) @@ -843,20 +750,23 @@ class MRPipe(CLSBasePipe): class R8Pipe(CLSBasePipe): - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc = 0): - r""" + """ + 加载 **R8** 的数据。 - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc = 0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = R8Loader().load(paths) @@ -866,20 +776,23 @@ class R8Pipe(CLSBasePipe): class R52Pipe(CLSBasePipe): - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): - r""" + """ + 加载 **R52** 的数据。 - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = R52Loader().load(paths) @@ -889,20 +802,23 @@ class R52Pipe(CLSBasePipe): class OhsumedPipe(CLSBasePipe): - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): - r""" + """ + 加载 **Ohsumed** 的数据。 - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = OhsumedLoader().load(paths) @@ -912,20 +828,23 @@ class OhsumedPipe(CLSBasePipe): class NG20Pipe(CLSBasePipe): - def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): - r""" + """ + 加载 **NG20** 的数据。 - :param bool lower: 是否将words列的数据小写。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, lower: bool = False, tokenizer: str = 'spacy', num_proc: int = 0): super().__init__(tokenizer=tokenizer, lang='en', num_proc=num_proc) self.lower = lower def process_from_file(self, paths=None): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.Loader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = NG20Loader().load(paths) diff --git a/fastNLP/io/pipe/conll.py b/fastNLP/io/pipe/conll.py index efe05de0..3e4dceed 100644 --- a/fastNLP/io/pipe/conll.py +++ b/fastNLP/io/pipe/conll.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "Conll2003NERPipe", "Conll2003Pipe", @@ -60,7 +58,7 @@ class _NERPipe(Pipe): "[...]", "[...]" :param ~fastNLP.DataBundle data_bundle: 传入的DataBundle中的DataSet必须包含raw_words和ner两个field,且两个field的内容均为List[str]在传入DataBundle基础上原位修改。 - :return DataBundle: + :return: 处理后的 ``data_bundle`` """ # 转换tag for name, dataset in data_bundle.iter_datasets(): @@ -79,10 +77,14 @@ class _NERPipe(Pipe): class Conll2003NERPipe(_NERPipe): r""" - Conll2003的NER任务的处理Pipe, 该Pipe会(1)复制raw_words列,并命名为words; (2)在words, target列建立词表 - (创建 :class:`fastNLP.Vocabulary` 对象,所以在返回的DataBundle中将有两个Vocabulary); (3)将words,target列根据相应的 - Vocabulary转换为index。 - 经过该Pipe过后,DataSet中的内容如下所示 + **Conll2003** 的 **NER** 任务的处理 **Pipe** , 该Pipe会: + + 1. 复制 ``raw_words`` 列,并命名为 ``words`` ; + 2. 在 ``words`` , ``target`` 列建立词表,即创建 :class:`~fastNLP.core.Vocabulary` 对象,所以在返回的 + :class:`~fastNLP.io.DataBundle` 中将有两个 ``Vocabulary`` ; + 3. 将 ``words`` , ``target`` 列根据相应的词表转换为 index。 + + 处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: Following is a demo layout of DataSet returned by Conll2003Loader :header: "raw_words", "target", "words", "seq_len" @@ -91,27 +93,21 @@ class Conll2003NERPipe(_NERPipe): "[AL-AIN, United, Arab, ...]", "[3, 4,...]", "[4, 5, 6,...]", 6 "[...]", "[...]", "[...]", . - raw_words列为List[str], 是未转换的原始数据; words列为List[int],是转换为index的输入数据; target列是List[int],是转换为index的 - target。返回的DataSet中被设置为input有words, target, seq_len; 设置为target有target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ + ``raw_words`` 列为 :class:`List` [ :class:`str` ], 是未转换的原始数据; ``words`` 列为 :class:`List` [ :class:`int` ], + 是转换为 index 的输入数据; ``target`` 列是 :class:`List` [ :class:`int` ] ,是转换为 index 的 target。返回的 :class:`~fastNLP.core.DataSet` + 中被设置为 input 有 ``words`` , ``target``, ``seq_len``;target 有 ``target`` 。 + :param encoding_type: ``target`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param lower: 是否将 ``words`` 小写化后再建立词表,绝大多数情况都不需要设置为 ``True`` 。 + :param num_proc: 处理数据时使用的进程数目。 """ def process_from_file(self, paths) -> DataBundle: r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param paths: 支持路径类型参见 :class:`fastNLP.io.loader.ConllLoader` 的load函数。 - :return: DataBundle + :param paths: + :return: """ # 读取数据 data_bundle = Conll2003NERLoader().load(paths) @@ -122,7 +118,7 @@ class Conll2003NERPipe(_NERPipe): class Conll2003Pipe(Pipe): r""" - 经过该Pipe后,DataSet中的内容如下 + 处理 **Conll2003** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words" , "pos", "chunk", "ner", "words", "seq_len" @@ -131,27 +127,14 @@ class Conll2003Pipe(Pipe): "[AL-AIN, United, Arab, ...]", "[1, 2...]", "[3, 4...]", "[3, 4...]", "[4, 5, 6,...]", 6 "[...]", "[...]", "[...]", "[...]", "[...]", . - 其中words, seq_len是input; pos, chunk, ner, seq_len是target - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+-------+-------+-------+-------+---------+ - | field_names | raw_words | pos | chunk | ner | words | seq_len | - +-------------+-----------+-------+-------+-------+-------+---------+ - | is_input | False | False | False | False | True | True | - | is_target | False | True | True | True | False | True | - | ignore_type | | False | False | False | False | False | - | pad_value | | 0 | 0 | 0 | 0 | 0 | - +-------------+-----------+-------+-------+-------+-------+---------+ - + 其中``words``, ``seq_len`` 是 input; ``pos``, ``chunk``, ``ner``, ``seq_len`` 是 target + :param chunk_encoding_type: ``chunk`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param ner_encoding_type: ``ner`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param lower: 是否将 ``words`` 小写化后再建立词表,绝大多数情况都不需要设置为 ``True`` 。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, chunk_encoding_type='bioes', ner_encoding_type='bioes', lower: bool = False, num_proc: int = 0): - r""" - - :param str chunk_encoding_type: 支持bioes, bio。 - :param str ner_encoding_type: 支持bioes, bio。 - :param bool lower: 是否将words列小写化后再建立词表 - """ + def __init__(self, chunk_encoding_type: str='bioes', ner_encoding_type: str='bioes', lower: bool = False, num_proc: int = 0): if chunk_encoding_type == 'bio': self.chunk_convert_tag = iob2 elif chunk_encoding_type == 'bioes': @@ -175,7 +158,7 @@ class Conll2003Pipe(Pipe): def process(self, data_bundle) -> DataBundle: r""" - 输入的DataSet应该类似于如下的形式 + 输入的 `~fastNLP.core.DataSet` 应该类似于如下的形式: .. csv-table:: :header: "raw_words", "pos", "chunk", "ner" @@ -185,7 +168,7 @@ class Conll2003Pipe(Pipe): "[...]", "[...]", "[...]", "[...]", . :param data_bundle: - :return: 传入的DataBundle + :return: 处理后的 ``data_bundle`` """ # 转换tag for name, dataset in data_bundle.datasets.items(): @@ -210,6 +193,7 @@ class Conll2003Pipe(Pipe): def process_from_file(self, paths): r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` :param paths: :return: @@ -220,7 +204,7 @@ class Conll2003Pipe(Pipe): class OntoNotesNERPipe(_NERPipe): r""" - 处理OntoNotes的NER数据,处理之后DataSet中的field情况为 + 处理 **OntoNotes** 的 **NER** 数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words", "target", "words", "seq_len" @@ -229,23 +213,19 @@ class OntoNotesNERPipe(_NERPipe): "[AL-AIN, United, Arab, ...]", "[3, 4]", "[4, 5, 6,...]", 6 "[...]", "[...]", "[...]", . - raw_words列为List[str], 是未转换的原始数据; words列为List[int],是转换为index的输入数据; target列是List[int],是转换为index的 - target。返回的DataSet中被设置为input有words, target, seq_len; 设置为target有target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_words | target | words | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ + ``raw_words`` 列为 :class:`List` [ :class:`str` ], 是未转换的原始数据; ``words`` 列为 :class:`List` [ :class:`int` ], + 是转换为 index 的输入数据; ``target`` 列是 :class:`List` [ :class:`int` ] ,是转换为 index 的 target。返回的 :class:`~fastNLP.core.DataSet` + 中被设置为 input 有 ``words`` , ``target``, ``seq_len``;target 有 ``target`` 。 """ def process_from_file(self, paths): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = OntoNotesNERLoader().load(paths) return self.process(data_bundle) @@ -301,7 +281,7 @@ class _CNNERPipe(Pipe): 是转换为index的target。返回的DataSet中被设置为input有chars, target, seq_len; 设置为target有target。 :param ~fastNLP.DataBundle data_bundle: 传入的DataBundle中的DataSet必须包含raw_words和ner两个field,且两个field的内容均为List[str]。在传入DataBundle基础上原位修改。 - :return: DataBundle + :return: 处理后的 ``data_bundle`` """ # 转换tag for name, dataset in data_bundle.datasets.items(): @@ -338,7 +318,7 @@ class _CNNERPipe(Pipe): class MsraNERPipe(_CNNERPipe): r""" - 处理MSRA-NER的数据,处理之后的DataSet的field情况为 + 处理 **MSRA-NER** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_chars", "target", "chars", "seq_len" @@ -347,30 +327,34 @@ class MsraNERPipe(_CNNERPipe): "[青, 岛, 海, 牛, 队, 和, ...]", "[1, 2, 3, ...]", "[10, 21, ....]", 21 "[...]", "[...]", "[...]", . - raw_chars列为List[str], 是未转换的原始数据; chars列为List[int],是转换为index的输入数据; target列是List[int],是转换为index的 - target。返回的DataSet中被设置为input有chars, target, seq_len; 设置为target有target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + ``raw_chars`` 列为 :class:`List` [ :class:`str` ], 是未转换的原始数据; ``chars`` 列为 :class:`List` [ :class:`int` ], + 是转换为 index 的输入数据; ``target`` 列是 :class:`List` [ :class:`int` ] ,是转换为 index 的 target。返回的 :class:`~fastNLP.core.DataSet` + 中被设置为 input 有 ``chars`` , ``target``, ``seq_len``;target 有 ``target`` 。 + + :param encoding_type: ``target`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ def process_from_file(self, paths=None) -> DataBundle: + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = MsraNERLoader().load(paths) return self.process(data_bundle) class PeopleDailyPipe(_CNNERPipe): r""" - 处理people daily的ner的数据,处理之后的DataSet的field情况为 + 处理 **People's Daily NER** 的 **ner** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_chars", "target", "chars", "seq_len" @@ -379,30 +363,34 @@ class PeopleDailyPipe(_CNNERPipe): "[青, 岛, 海, 牛, 队, 和, ...]", "[1, 2, 3, ...]", "[10, 21, ....]", 21 "[...]", "[...]", "[...]", . - raw_chars列为List[str], 是未转换的原始数据; chars列为List[int],是转换为index的输入数据; target列是List[int],是转换为index的 - target。返回的DataSet中被设置为input有chars, target, seq_len; 设置为target有target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + ``raw_chars`` 列为 :class:`List` [ :class:`str` ], 是未转换的原始数据; ``chars`` 列为 :class:`List` [ :class:`int` ], + 是转换为 index 的输入数据; ``target`` 列是 :class:`List` [ :class:`int` ] ,是转换为 index 的 target。返回的 :class:`~fastNLP.core.DataSet` + 中被设置为 input 有 ``chars`` , ``target``, ``seq_len``;target 有 ``target`` 。 + + :param encoding_type: ``target`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ def process_from_file(self, paths=None) -> DataBundle: + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = PeopleDailyNERLoader().load(paths) return self.process(data_bundle) class WeiboNERPipe(_CNNERPipe): r""" - 处理weibo的ner的数据,处理之后的DataSet的field情况为 + 处理 **Weibo** 的 **BER** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_chars", "chars", "target", "seq_len" @@ -411,22 +399,26 @@ class WeiboNERPipe(_CNNERPipe): "['心']", "[0]", "[41]", 1 "[...]", "[...]", "[...]", . - raw_chars列为List[str], 是未转换的原始数据; chars列为List[int],是转换为index的输入数据; target列是List[int],是转换为index的 - target。返回的DataSet中被设置为input有chars, target, seq_len; 设置为target有target。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+--------+-------+---------+ - | field_names | raw_chars | target | chars | seq_len | - +-------------+-----------+--------+-------+---------+ - | is_input | False | True | True | True | - | is_target | False | True | False | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+--------+-------+---------+ - + ``raw_chars`` 列为 :class:`List` [ :class:`str` ], 是未转换的原始数据; ``chars`` 列为 :class:`List` [ :class:`int` ], + 是转换为 index 的输入数据; ``target`` 列是 :class:`List` [ :class:`int` ] ,是转换为 index 的 target。返回的 :class:`~fastNLP.core.DataSet` + 中被设置为 input 有 ``chars`` , ``target``, ``seq_len``;target 有 ``target`` 。 + + :param encoding_type: ``target`` 列使用什么类型的 encoding 方式,支持 ``['bioes', 'bio']`` 两种。 + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ def process_from_file(self, paths=None) -> DataBundle: + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = WeiboNERLoader().load(paths) return self.process(data_bundle) diff --git a/fastNLP/io/pipe/construct_graph.py b/fastNLP/io/pipe/construct_graph.py index 1448765e..ebb0315a 100644 --- a/fastNLP/io/pipe/construct_graph.py +++ b/fastNLP/io/pipe/construct_graph.py @@ -173,14 +173,20 @@ class GraphBuilderBase: class MRPmiGraphPipe(GraphBuilderBase): + """ + 构建 **MR** 数据集的 **Graph** 。 + :param graph_type: + :param widow_size: + :param threshold: + """ def __init__(self, graph_type='pmi', widow_size=10, threshold=0.): super().__init__(graph_type=graph_type, widow_size=widow_size, threshold=threshold) def build_graph(self, data_bundle: DataBundle): r""" - params: ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象. - return 返回csr类型的稀疏矩阵图;训练集,验证集,测试集,在图中的index. + :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) self._get_word_edge() @@ -190,19 +196,31 @@ class MRPmiGraphPipe(GraphBuilderBase): self.tr_doc_index, self.dev_doc_index, self.te_doc_index) def build_graph_from_file(self, path: str): + r""" + 传入文件路径,生成处理好的 ``scipy_sparse_matrix`` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` + + :param path: 数据集的路径。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 + """ data_bundle = MRLoader().load(path) return self.build_graph(data_bundle) class R8PmiGraphPipe(GraphBuilderBase): + """ + 构建 **R8** 数据集的 **Graph** 。 + :param graph_type: + :param widow_size: + :param threshold: + """ def __init__(self, graph_type='pmi', widow_size=10, threshold=0.): super().__init__(graph_type=graph_type, widow_size=widow_size, threshold=threshold) def build_graph(self, data_bundle: DataBundle): r""" - params: ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象. - return 返回csr类型的稀疏矩阵图;训练集,验证集,测试集,在图中的index. + :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) self._get_word_edge() @@ -212,19 +230,31 @@ class R8PmiGraphPipe(GraphBuilderBase): self.tr_doc_index, self.dev_doc_index, self.te_doc_index) def build_graph_from_file(self, path: str): + r""" + 传入文件路径,生成处理好的 ``scipy_sparse_matrix`` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` + + :param path: 数据集的路径。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 + """ data_bundle = R8Loader().load(path) return self.build_graph(data_bundle) class R52PmiGraphPipe(GraphBuilderBase): + """ + 构建 **R52** 数据集的 **Graph** 。 + :param graph_type: + :param widow_size: + :param threshold: + """ def __init__(self, graph_type='pmi', widow_size=10, threshold=0.): super().__init__(graph_type=graph_type, widow_size=widow_size, threshold=threshold) def build_graph(self, data_bundle: DataBundle): r""" - params: ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象. - return 返回csr类型的稀疏矩阵;训练集,验证集,测试集,在图中的index. + :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) self._get_word_edge() @@ -234,19 +264,31 @@ class R52PmiGraphPipe(GraphBuilderBase): self.tr_doc_index, self.dev_doc_index, self.te_doc_index) def build_graph_from_file(self, path: str): + r""" + 传入文件路径,生成处理好的 ``scipy_sparse_matrix`` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` + + :param path: 数据集的路径。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 + """ data_bundle = R52Loader().load(path) return self.build_graph(data_bundle) class OhsumedPmiGraphPipe(GraphBuilderBase): + """ + 构建 **Ohsuned** 数据集的 **Graph** 。 + :param graph_type: + :param widow_size: + :param threshold: + """ def __init__(self, graph_type='pmi', widow_size=10, threshold=0.): super().__init__(graph_type=graph_type, widow_size=widow_size, threshold=threshold) def build_graph(self, data_bundle: DataBundle): r""" - params: ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象. - return 返回csr类型的稀疏矩阵图;训练集,验证集,测试集,在图中的index. + :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) self._get_word_edge() @@ -256,19 +298,31 @@ class OhsumedPmiGraphPipe(GraphBuilderBase): self.tr_doc_index, self.dev_doc_index, self.te_doc_index) def build_graph_from_file(self, path: str): + r""" + 传入文件路径,生成处理好的 ``scipy_sparse_matrix`` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` + + :param path: 数据集的路径。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 + """ data_bundle = OhsumedLoader().load(path) return self.build_graph(data_bundle) class NG20PmiGraphPipe(GraphBuilderBase): + """ + 构建 **NG20** 数据集的 **Graph** 。 + :param graph_type: + :param widow_size: + :param threshold: + """ def __init__(self, graph_type='pmi', widow_size=10, threshold=0.): super().__init__(graph_type=graph_type, widow_size=widow_size, threshold=threshold) def build_graph(self, data_bundle: DataBundle): r""" - params: ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象. - return 返回csr类型的稀疏矩阵图;训练集,验证集,测试集,在图中的index. + :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) self._get_word_edge() @@ -279,8 +333,10 @@ class NG20PmiGraphPipe(GraphBuilderBase): def build_graph_from_file(self, path: str): r""" - param: path->数据集的路径. - return: 返回csr类型的稀疏矩阵图;训练集,验证集,测试集,在图中的index. + 传入文件路径,生成处理好的 ``scipy_sparse_matrix`` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` + + :param path: 数据集的路径。 + :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ data_bundle = NG20Loader().load(path) return self.build_graph(data_bundle) diff --git a/fastNLP/io/pipe/cws.py b/fastNLP/io/pipe/cws.py index 2937f147..0afc9851 100644 --- a/fastNLP/io/pipe/cws.py +++ b/fastNLP/io/pipe/cws.py @@ -230,7 +230,7 @@ class CWSPipe(Pipe): "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ data_bundle.copy_field('raw_words', 'chars') @@ -276,8 +276,9 @@ class CWSPipe(Pipe): def process_from_file(self, paths=None) -> DataBundle: r""" - - :param str paths: + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: :return: """ if self.dataset_name is None and paths is None: diff --git a/fastNLP/io/pipe/matching.py b/fastNLP/io/pipe/matching.py index 5b9981c2..ecaace9d 100644 --- a/fastNLP/io/pipe/matching.py +++ b/fastNLP/io/pipe/matching.py @@ -165,30 +165,60 @@ class MatchingBertPipe(Pipe): class RTEBertPipe(MatchingBertPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = RTELoader().load(paths) return self.process(data_bundle) class SNLIBertPipe(MatchingBertPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = SNLILoader().load(paths) return self.process(data_bundle) class QuoraBertPipe(MatchingBertPipe): def process_from_file(self, paths): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = QuoraLoader().load(paths) return self.process(data_bundle) class QNLIBertPipe(MatchingBertPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = QNLILoader().load(paths) return self.process(data_bundle) class MNLIBertPipe(MatchingBertPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = MNLILoader().load(paths) return self.process(data_bundle) @@ -308,30 +338,60 @@ class MatchingPipe(Pipe): class RTEPipe(MatchingPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = RTELoader().load(paths) return self.process(data_bundle) class SNLIPipe(MatchingPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = SNLILoader().load(paths) return self.process(data_bundle) class QuoraPipe(MatchingPipe): def process_from_file(self, paths): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = QuoraLoader().load(paths) return self.process(data_bundle) class QNLIPipe(MatchingPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = QNLILoader().load(paths) return self.process(data_bundle) class MNLIPipe(MatchingPipe): def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = MNLILoader().load(paths) return self.process(data_bundle) @@ -341,6 +401,12 @@ class LCQMCPipe(MatchingPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = LCQMCLoader().load(paths) data_bundle = RenamePipe().process(data_bundle) data_bundle = self.process(data_bundle) @@ -353,6 +419,12 @@ class CNXNLIPipe(MatchingPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = CNXNLILoader().load(paths) data_bundle = GranularizePipe(task='XNLI').process(data_bundle) data_bundle = RenamePipe().process(data_bundle) # 使中文数据的field @@ -366,6 +438,12 @@ class BQCorpusPipe(MatchingPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = BQCorpusLoader().load(paths) data_bundle = RenamePipe().process(data_bundle) data_bundle = self.process(data_bundle) @@ -380,6 +458,10 @@ class RenamePipe(Pipe): self.num_proc = num_proc def process(self, data_bundle: DataBundle): # rename field name for Chinese Matching dataset + """ + + :return: 处理后的 ``data_bundle`` + """ if (self.task == 'cn-nli'): for name, dataset in data_bundle.datasets.items(): if (dataset.has_field('raw_chars1')): @@ -437,6 +519,10 @@ class GranularizePipe(Pipe): return data_bundle def process(self, data_bundle: DataBundle): + """ + + :return: 处理后的 ``data_bundle`` + """ task_tag_dict = { 'XNLI': {'neutral': 0, 'entailment': 1, 'contradictory': 2, 'contradiction': 2} } @@ -452,6 +538,10 @@ class MachingTruncatePipe(Pipe): # truncate sentence for bert, modify seq_len super().__init__() def process(self, data_bundle: DataBundle): + """ + + :return: None + """ for name, dataset in data_bundle.datasets.items(): pass return None @@ -462,6 +552,12 @@ class LCQMCBertPipe(MatchingBertPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = LCQMCLoader().load(paths) data_bundle = RenamePipe(task='cn-nli-bert').process(data_bundle) data_bundle = self.process(data_bundle) @@ -475,6 +571,12 @@ class BQCorpusBertPipe(MatchingBertPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = BQCorpusLoader().load(paths) data_bundle = RenamePipe(task='cn-nli-bert').process(data_bundle) data_bundle = self.process(data_bundle) @@ -488,6 +590,12 @@ class CNXNLIBertPipe(MatchingBertPipe): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = CNXNLILoader().load(paths) data_bundle = GranularizePipe(task='XNLI').process(data_bundle) data_bundle = RenamePipe(task='cn-nli-bert').process(data_bundle) @@ -522,6 +630,10 @@ class TruncateBertPipe(Pipe): return words_before_sep + words_after_sep def process(self, data_bundle: DataBundle) -> DataBundle: + """ + + :return: 处理后的 ``data_bundle`` + """ for name in data_bundle.datasets.keys(): dataset = data_bundle.get_dataset(name) sep_index_vocab = data_bundle.get_vocab('words').to_index('[SEP]') diff --git a/fastNLP/io/pipe/pipe.py b/fastNLP/io/pipe/pipe.py index 4916bf09..68106c17 100644 --- a/fastNLP/io/pipe/pipe.py +++ b/fastNLP/io/pipe/pipe.py @@ -27,15 +27,15 @@ class Pipe: 对输入的DataBundle进行处理,然后返回该DataBundle。 :param ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象 - :return: DataBundle + :return: 处理后的 ``data_bundle`` """ raise NotImplementedError def process_from_file(self, paths: str) -> DataBundle: r""" - 传入文件路径,生成处理好的DataBundle对象。paths支持的路径形式可以参考 ::meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` - :param str paths: - :return: DataBundle + :param paths: + :return: """ raise NotImplementedError diff --git a/fastNLP/io/pipe/qa.py b/fastNLP/io/pipe/qa.py index 23fe1367..2deb4085 100644 --- a/fastNLP/io/pipe/qa.py +++ b/fastNLP/io/pipe/qa.py @@ -122,7 +122,7 @@ class CMRC2018BertPipe(Pipe): "...", "...", "...","...", ".", "..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ data_bundle = _concat_clip(data_bundle, max_len=self.max_len, concat_field_name='raw_chars') @@ -138,5 +138,11 @@ class CMRC2018BertPipe(Pipe): return data_bundle def process_from_file(self, paths=None) -> DataBundle: + r""" + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: + """ data_bundle = CMRC2018Loader().load(paths) return self.process(data_bundle) diff --git a/fastNLP/io/pipe/summarization.py b/fastNLP/io/pipe/summarization.py index b413890b..eb56a2c8 100644 --- a/fastNLP/io/pipe/summarization.py +++ b/fastNLP/io/pipe/summarization.py @@ -54,7 +54,7 @@ class ExtCNNDMPipe(Pipe): ["..."], ["..."], [], "cnndm" :param data_bundle: - :return: 处理得到的数据包括 + :return: 处理后的 ``data_bundle`` .. csv-table:: :header: "text_wd", "words", "seq_len", "target" @@ -117,8 +117,10 @@ class ExtCNNDMPipe(Pipe): def process_from_file(self, paths=None): r""" - :param paths: dict or string - :return: DataBundle + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + + :param paths: + :return: """ loader = ExtCNNDMLoader() if self.vocab_path is None: diff --git a/fastNLP/io/pipe/utils.py b/fastNLP/io/pipe/utils.py index c5c32d95..50047d04 100644 --- a/fastNLP/io/pipe/utils.py +++ b/fastNLP/io/pipe/utils.py @@ -82,7 +82,7 @@ def get_tokenizer(tokenize_method: str, lang='en'): import spacy spacy.prefer_gpu() if lang != 'en': - raise RuntimeError("Spacy only supports en right right.") + raise RuntimeError("Spacy only supports en right now.") if parse_version(spacy.__version__) >= parse_version('3.0'): en = spacy.load('en_core_web_sm') else: diff --git a/fastNLP/io/utils.py b/fastNLP/io/utils.py index 79806794..57a283ba 100644 --- a/fastNLP/io/utils.py +++ b/fastNLP/io/utils.py @@ -1,8 +1,3 @@ -r""" -.. todo:: - doc -""" - __all__ = [ "check_loader_paths" ] @@ -16,7 +11,7 @@ from typing import Union, Dict def check_loader_paths(paths: Union[str, Dict[str, str]]) -> Dict[str, str]: r""" - 检查传入dataloader的文件的合法性。如果为合法路径,将返回至少包含'train'这个key的dict。类似于下面的结果:: + 检查传入 ``dataloader`` 的文件的合法性。如果为合法路径,将返回至少包含 ``'train'`` 这个 key 的字典。类似于下面的结果:: { 'train': '/some/path/to/', # 一定包含,建词表应该在这上面建立,剩下的其它文件应该只需要处理并index。 @@ -24,10 +19,13 @@ def check_loader_paths(paths: Union[str, Dict[str, str]]) -> Dict[str, str]: ... } - 如果paths为不合法的,将直接进行raise相应的错误. 如果paths内不包含train也会报错。 + 如果 ``paths`` 为不合法的,将直接进行 raise 相应的错误。如果 ``paths`` 内不包含 ``'train'`` 也会报错。 - :param str paths: 路径. 可以为一个文件路径(则认为该文件就是train的文件); 可以为一个文件目录,将在该目录下寻找包含train(文件名 - 中包含train这个字段), test, dev这三个字段的文件或文件夹; 可以为一个dict, 则key是用户自定义的某个文件的名称,value是这个文件的路径。 + :param str paths: 路径。可以为: + + - 一个文件路径,此时认为该文件就是 train 的文件; + - 一个文件目录,将在该目录下寻找包含 ``train`` (文件名中包含 train 这个字段), ``test`` ,``dev`` 这三个字段的文件或文件夹; + - 一个 dict, 则 key 是用户自定义的某个文件的名称,value 是这个文件的路径。 :return: """ if isinstance(paths, (str, Path)): diff --git a/fastNLP/transformers/__init__.py b/fastNLP/transformers/__init__.py index 6403f6b9..3b375020 100644 --- a/fastNLP/transformers/__init__.py +++ b/fastNLP/transformers/__init__.py @@ -1 +1,4 @@ -"""基于 transformers-4.11.3 版本迁移""" \ No newline at end of file +""" +:mod:`transformers` 模块,包含了常用的预训练模型。 +""" +import sphinx-multiversion \ No newline at end of file diff --git a/fastNLP/transformers/torch/__init__.py b/fastNLP/transformers/torch/__init__.py index 9ce4fb10..3b564cd4 100644 --- a/fastNLP/transformers/torch/__init__.py +++ b/fastNLP/transformers/torch/__init__.py @@ -1,9 +1,15 @@ """ -为了防止因 https://github.com/huggingface/transformers 版本变化导致代码不兼容,当前 folder 以及子 folder -都复制自 https://github.com/huggingface/transformers 的4.11.3版本。 -In order to avoid the code change of https://github.com/huggingface/transformers to cause version -mismatch, we copy code from https://github.com/huggingface/transformers(version:4.11.3) in this +为了防止因 `transformers `_ 版本变化导致代码不兼容,当前文件夹以及子文件夹 +都复制自 `transformers `_ 的 4.11.3 版本。 + +In order to avoid the code change of `transformers `_ to cause version +mismatch, we copy code from `transformers `_ (version:4.11.3) in this folder and its subfolder. + +您可以如下面代码所示使用 transformers:: + + from fastNLP.transformers.torch import BertModel + ... """ __version__ = "4.11.3" from .models import * \ No newline at end of file From 819897a4f6a5375eb8c749a44f30a6aecf93ad79 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:23:02 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=9A=84rst=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fastNLP.core.callbacks.timer_callback.rst | 7 +++++ ....core.collators.padders.oneflow_padder.rst | 7 +++++ ...ore.dataloaders.oneflow_dataloader.fdl.rst | 7 +++++ ...LP.core.dataloaders.oneflow_dataloader.rst | 15 +++++++++++ ...oaders.torch_dataloader.mix_dataloader.rst | 7 +++++ ...astNLP.core.drivers.oneflow_driver.ddp.rst | 7 +++++ ...core.drivers.oneflow_driver.dist_utils.rst | 7 +++++ ...eflow_driver.initialize_oneflow_driver.rst | 7 +++++ ....drivers.oneflow_driver.oneflow_driver.rst | 7 +++++ .../fastNLP.core.drivers.oneflow_driver.rst | 20 ++++++++++++++ ...e.drivers.oneflow_driver.single_device.rst | 7 +++++ ...tNLP.core.drivers.oneflow_driver.utils.rst | 7 +++++ ...LP.core.drivers.torch_driver.deepspeed.rst | 7 +++++ ...LP.core.drivers.torch_driver.fairscale.rst | 7 +++++ ...P.core.drivers.torch_driver.torch_fsdp.rst | 7 +++++ ...etrics.backend.oneflow_backend.backend.rst | 7 +++++ ...P.core.metrics.backend.oneflow_backend.rst | 15 +++++++++++ .../fastNLP.core.utils.oneflow_utils.rst | 7 +++++ .../fastNLP.core.utils.seq_len_to_mask.rst | 7 +++++ .../fastNLP.core.utils.tqdm_progress.rst | 7 +++++ docs/source/fastNLP.embeddings.rst | 15 +++++++++++ ...astNLP.embeddings.torch.char_embedding.rst | 7 +++++ .../fastNLP.embeddings.torch.embedding.rst | 7 +++++ docs/source/fastNLP.embeddings.torch.rst | 19 ++++++++++++++ ...stNLP.embeddings.torch.stack_embedding.rst | 7 +++++ ...tNLP.embeddings.torch.static_embedding.rst | 7 +++++ .../source/fastNLP.embeddings.torch.utils.rst | 7 +++++ docs/source/fastNLP.models.rst | 15 +++++++++++ .../fastNLP.models.torch.biaffine_parser.rst | 7 +++++ ...P.models.torch.cnn_text_classification.rst | 7 +++++ docs/source/fastNLP.models.torch.rst | 19 ++++++++++++++ ...fastNLP.models.torch.seq2seq_generator.rst | 7 +++++ .../fastNLP.models.torch.seq2seq_model.rst | 7 +++++ ...fastNLP.models.torch.sequence_labeling.rst | 7 +++++ .../fastNLP.modules.torch.attention.rst | 7 +++++ .../fastNLP.modules.torch.decoder.crf.rst | 7 +++++ .../fastNLP.modules.torch.decoder.mlp.rst | 7 +++++ docs/source/fastNLP.modules.torch.decoder.rst | 18 +++++++++++++ ....modules.torch.decoder.seq2seq_decoder.rst | 7 +++++ ...LP.modules.torch.decoder.seq2seq_state.rst | 7 +++++ docs/source/fastNLP.modules.torch.dropout.rst | 7 +++++ ...NLP.modules.torch.encoder.conv_maxpool.rst | 7 +++++ .../fastNLP.modules.torch.encoder.lstm.rst | 7 +++++ docs/source/fastNLP.modules.torch.encoder.rst | 20 ++++++++++++++ ....modules.torch.encoder.seq2seq_encoder.rst | 7 +++++ ...modules.torch.encoder.star_transformer.rst | 7 +++++ ...tNLP.modules.torch.encoder.transformer.rst | 7 +++++ ....modules.torch.encoder.variational_rnn.rst | 7 +++++ .../fastNLP.modules.torch.generator.rst | 15 +++++++++++ ...ules.torch.generator.seq2seq_generator.rst | 7 +++++ docs/source/fastNLP.modules.torch.rst | 26 +++++++++++++++++++ docs/source/fastNLP.transformers.rst | 15 +++++++++++ docs/source/fastNLP.transformers.torch.rst | 7 +++++ docs/source/index.rst | 8 +++--- docs/source/tutorials.rst | 8 ++++++ 55 files changed, 511 insertions(+), 4 deletions(-) create mode 100644 docs/source/fastNLP.core.callbacks.timer_callback.rst create mode 100644 docs/source/fastNLP.core.collators.padders.oneflow_padder.rst create mode 100644 docs/source/fastNLP.core.dataloaders.oneflow_dataloader.fdl.rst create mode 100644 docs/source/fastNLP.core.dataloaders.oneflow_dataloader.rst create mode 100644 docs/source/fastNLP.core.dataloaders.torch_dataloader.mix_dataloader.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.ddp.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.dist_utils.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.oneflow_driver.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.single_device.rst create mode 100644 docs/source/fastNLP.core.drivers.oneflow_driver.utils.rst create mode 100644 docs/source/fastNLP.core.drivers.torch_driver.deepspeed.rst create mode 100644 docs/source/fastNLP.core.drivers.torch_driver.fairscale.rst create mode 100644 docs/source/fastNLP.core.drivers.torch_driver.torch_fsdp.rst create mode 100644 docs/source/fastNLP.core.metrics.backend.oneflow_backend.backend.rst create mode 100644 docs/source/fastNLP.core.metrics.backend.oneflow_backend.rst create mode 100644 docs/source/fastNLP.core.utils.oneflow_utils.rst create mode 100644 docs/source/fastNLP.core.utils.seq_len_to_mask.rst create mode 100644 docs/source/fastNLP.core.utils.tqdm_progress.rst create mode 100644 docs/source/fastNLP.embeddings.rst create mode 100644 docs/source/fastNLP.embeddings.torch.char_embedding.rst create mode 100644 docs/source/fastNLP.embeddings.torch.embedding.rst create mode 100644 docs/source/fastNLP.embeddings.torch.rst create mode 100644 docs/source/fastNLP.embeddings.torch.stack_embedding.rst create mode 100644 docs/source/fastNLP.embeddings.torch.static_embedding.rst create mode 100644 docs/source/fastNLP.embeddings.torch.utils.rst create mode 100644 docs/source/fastNLP.models.rst create mode 100644 docs/source/fastNLP.models.torch.biaffine_parser.rst create mode 100644 docs/source/fastNLP.models.torch.cnn_text_classification.rst create mode 100644 docs/source/fastNLP.models.torch.rst create mode 100644 docs/source/fastNLP.models.torch.seq2seq_generator.rst create mode 100644 docs/source/fastNLP.models.torch.seq2seq_model.rst create mode 100644 docs/source/fastNLP.models.torch.sequence_labeling.rst create mode 100644 docs/source/fastNLP.modules.torch.attention.rst create mode 100644 docs/source/fastNLP.modules.torch.decoder.crf.rst create mode 100644 docs/source/fastNLP.modules.torch.decoder.mlp.rst create mode 100644 docs/source/fastNLP.modules.torch.decoder.rst create mode 100644 docs/source/fastNLP.modules.torch.decoder.seq2seq_decoder.rst create mode 100644 docs/source/fastNLP.modules.torch.decoder.seq2seq_state.rst create mode 100644 docs/source/fastNLP.modules.torch.dropout.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.conv_maxpool.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.lstm.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.seq2seq_encoder.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.star_transformer.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.transformer.rst create mode 100644 docs/source/fastNLP.modules.torch.encoder.variational_rnn.rst create mode 100644 docs/source/fastNLP.modules.torch.generator.rst create mode 100644 docs/source/fastNLP.modules.torch.generator.seq2seq_generator.rst create mode 100644 docs/source/fastNLP.modules.torch.rst create mode 100644 docs/source/fastNLP.transformers.rst create mode 100644 docs/source/fastNLP.transformers.torch.rst create mode 100644 docs/source/tutorials.rst diff --git a/docs/source/fastNLP.core.callbacks.timer_callback.rst b/docs/source/fastNLP.core.callbacks.timer_callback.rst new file mode 100644 index 00000000..884fa604 --- /dev/null +++ b/docs/source/fastNLP.core.callbacks.timer_callback.rst @@ -0,0 +1,7 @@ +fastNLP.core.callbacks.timer\_callback module +============================================= + +.. automodule:: fastNLP.core.callbacks.timer_callback + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.collators.padders.oneflow_padder.rst b/docs/source/fastNLP.core.collators.padders.oneflow_padder.rst new file mode 100644 index 00000000..ced75ccb --- /dev/null +++ b/docs/source/fastNLP.core.collators.padders.oneflow_padder.rst @@ -0,0 +1,7 @@ +fastNLP.core.collators.padders.oneflow\_padder module +===================================================== + +.. automodule:: fastNLP.core.collators.padders.oneflow_padder + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.fdl.rst b/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.fdl.rst new file mode 100644 index 00000000..5a8939b0 --- /dev/null +++ b/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.fdl.rst @@ -0,0 +1,7 @@ +fastNLP.core.dataloaders.oneflow\_dataloader.fdl module +======================================================= + +.. automodule:: fastNLP.core.dataloaders.oneflow_dataloader.fdl + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.rst b/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.rst new file mode 100644 index 00000000..2b2081e5 --- /dev/null +++ b/docs/source/fastNLP.core.dataloaders.oneflow_dataloader.rst @@ -0,0 +1,15 @@ +fastNLP.core.dataloaders.oneflow\_dataloader package +==================================================== + +.. automodule:: fastNLP.core.dataloaders.oneflow_dataloader + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.core.dataloaders.oneflow_dataloader.fdl diff --git a/docs/source/fastNLP.core.dataloaders.torch_dataloader.mix_dataloader.rst b/docs/source/fastNLP.core.dataloaders.torch_dataloader.mix_dataloader.rst new file mode 100644 index 00000000..cd8bd865 --- /dev/null +++ b/docs/source/fastNLP.core.dataloaders.torch_dataloader.mix_dataloader.rst @@ -0,0 +1,7 @@ +fastNLP.core.dataloaders.torch\_dataloader.mix\_dataloader module +================================================================= + +.. automodule:: fastNLP.core.dataloaders.torch_dataloader.mix_dataloader + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.ddp.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.ddp.rst new file mode 100644 index 00000000..c7618619 --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.ddp.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.ddp module +=============================================== + +.. automodule:: fastNLP.core.drivers.oneflow_driver.ddp + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.dist_utils.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.dist_utils.rst new file mode 100644 index 00000000..9eae5d19 --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.dist_utils.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.dist\_utils module +======================================================= + +.. automodule:: fastNLP.core.drivers.oneflow_driver.dist_utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver.rst new file mode 100644 index 00000000..d7272c8e --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.initialize\_oneflow\_driver module +======================================================================= + +.. automodule:: fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.oneflow_driver.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.oneflow_driver.rst new file mode 100644 index 00000000..1f5d159e --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.oneflow_driver.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.oneflow\_driver module +=========================================================== + +.. automodule:: fastNLP.core.drivers.oneflow_driver.oneflow_driver + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.rst new file mode 100644 index 00000000..213dd24b --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.rst @@ -0,0 +1,20 @@ +fastNLP.core.drivers.oneflow\_driver package +============================================ + +.. automodule:: fastNLP.core.drivers.oneflow_driver + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.core.drivers.oneflow_driver.ddp + fastNLP.core.drivers.oneflow_driver.dist_utils + fastNLP.core.drivers.oneflow_driver.initialize_oneflow_driver + fastNLP.core.drivers.oneflow_driver.oneflow_driver + fastNLP.core.drivers.oneflow_driver.single_device + fastNLP.core.drivers.oneflow_driver.utils diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.single_device.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.single_device.rst new file mode 100644 index 00000000..a54e74ec --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.single_device.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.single\_device module +========================================================== + +.. automodule:: fastNLP.core.drivers.oneflow_driver.single_device + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.oneflow_driver.utils.rst b/docs/source/fastNLP.core.drivers.oneflow_driver.utils.rst new file mode 100644 index 00000000..1eda7794 --- /dev/null +++ b/docs/source/fastNLP.core.drivers.oneflow_driver.utils.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.oneflow\_driver.utils module +================================================= + +.. automodule:: fastNLP.core.drivers.oneflow_driver.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.torch_driver.deepspeed.rst b/docs/source/fastNLP.core.drivers.torch_driver.deepspeed.rst new file mode 100644 index 00000000..2944ffec --- /dev/null +++ b/docs/source/fastNLP.core.drivers.torch_driver.deepspeed.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.torch\_driver.deepspeed module +=================================================== + +.. automodule:: fastNLP.core.drivers.torch_driver.deepspeed + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.torch_driver.fairscale.rst b/docs/source/fastNLP.core.drivers.torch_driver.fairscale.rst new file mode 100644 index 00000000..e68972a7 --- /dev/null +++ b/docs/source/fastNLP.core.drivers.torch_driver.fairscale.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.torch\_driver.fairscale module +=================================================== + +.. automodule:: fastNLP.core.drivers.torch_driver.fairscale + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.torch_driver.torch_fsdp.rst b/docs/source/fastNLP.core.drivers.torch_driver.torch_fsdp.rst new file mode 100644 index 00000000..a799b7fc --- /dev/null +++ b/docs/source/fastNLP.core.drivers.torch_driver.torch_fsdp.rst @@ -0,0 +1,7 @@ +fastNLP.core.drivers.torch\_driver.torch\_fsdp module +===================================================== + +.. automodule:: fastNLP.core.drivers.torch_driver.torch_fsdp + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.metrics.backend.oneflow_backend.backend.rst b/docs/source/fastNLP.core.metrics.backend.oneflow_backend.backend.rst new file mode 100644 index 00000000..2389250b --- /dev/null +++ b/docs/source/fastNLP.core.metrics.backend.oneflow_backend.backend.rst @@ -0,0 +1,7 @@ +fastNLP.core.metrics.backend.oneflow\_backend.backend module +============================================================ + +.. automodule:: fastNLP.core.metrics.backend.oneflow_backend.backend + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.metrics.backend.oneflow_backend.rst b/docs/source/fastNLP.core.metrics.backend.oneflow_backend.rst new file mode 100644 index 00000000..cb9e9653 --- /dev/null +++ b/docs/source/fastNLP.core.metrics.backend.oneflow_backend.rst @@ -0,0 +1,15 @@ +fastNLP.core.metrics.backend.oneflow\_backend package +===================================================== + +.. automodule:: fastNLP.core.metrics.backend.oneflow_backend + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.core.metrics.backend.oneflow_backend.backend diff --git a/docs/source/fastNLP.core.utils.oneflow_utils.rst b/docs/source/fastNLP.core.utils.oneflow_utils.rst new file mode 100644 index 00000000..f9d11510 --- /dev/null +++ b/docs/source/fastNLP.core.utils.oneflow_utils.rst @@ -0,0 +1,7 @@ +fastNLP.core.utils.oneflow\_utils module +======================================== + +.. automodule:: fastNLP.core.utils.oneflow_utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.utils.seq_len_to_mask.rst b/docs/source/fastNLP.core.utils.seq_len_to_mask.rst new file mode 100644 index 00000000..55188a65 --- /dev/null +++ b/docs/source/fastNLP.core.utils.seq_len_to_mask.rst @@ -0,0 +1,7 @@ +fastNLP.core.utils.seq\_len\_to\_mask module +============================================ + +.. automodule:: fastNLP.core.utils.seq_len_to_mask + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.core.utils.tqdm_progress.rst b/docs/source/fastNLP.core.utils.tqdm_progress.rst new file mode 100644 index 00000000..cfcdc655 --- /dev/null +++ b/docs/source/fastNLP.core.utils.tqdm_progress.rst @@ -0,0 +1,7 @@ +fastNLP.core.utils.tqdm\_progress module +======================================== + +.. automodule:: fastNLP.core.utils.tqdm_progress + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.embeddings.rst b/docs/source/fastNLP.embeddings.rst new file mode 100644 index 00000000..1b220f59 --- /dev/null +++ b/docs/source/fastNLP.embeddings.rst @@ -0,0 +1,15 @@ +fastNLP.embeddings package +========================== + +.. automodule:: fastNLP.embeddings + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.embeddings.torch diff --git a/docs/source/fastNLP.embeddings.torch.char_embedding.rst b/docs/source/fastNLP.embeddings.torch.char_embedding.rst new file mode 100644 index 00000000..f0d1dad7 --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.char_embedding.rst @@ -0,0 +1,7 @@ +fastNLP.embeddings.torch.char\_embedding module +=============================================== + +.. automodule:: fastNLP.embeddings.torch.char_embedding + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.embeddings.torch.embedding.rst b/docs/source/fastNLP.embeddings.torch.embedding.rst new file mode 100644 index 00000000..1804a70e --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.embedding.rst @@ -0,0 +1,7 @@ +fastNLP.embeddings.torch.embedding module +========================================= + +.. automodule:: fastNLP.embeddings.torch.embedding + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.embeddings.torch.rst b/docs/source/fastNLP.embeddings.torch.rst new file mode 100644 index 00000000..6294e8a2 --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.rst @@ -0,0 +1,19 @@ +fastNLP.embeddings.torch package +================================ + +.. automodule:: fastNLP.embeddings.torch + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.embeddings.torch.char_embedding + fastNLP.embeddings.torch.embedding + fastNLP.embeddings.torch.stack_embedding + fastNLP.embeddings.torch.static_embedding + fastNLP.embeddings.torch.utils diff --git a/docs/source/fastNLP.embeddings.torch.stack_embedding.rst b/docs/source/fastNLP.embeddings.torch.stack_embedding.rst new file mode 100644 index 00000000..dab50088 --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.stack_embedding.rst @@ -0,0 +1,7 @@ +fastNLP.embeddings.torch.stack\_embedding module +================================================ + +.. automodule:: fastNLP.embeddings.torch.stack_embedding + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.embeddings.torch.static_embedding.rst b/docs/source/fastNLP.embeddings.torch.static_embedding.rst new file mode 100644 index 00000000..fc1a2bb9 --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.static_embedding.rst @@ -0,0 +1,7 @@ +fastNLP.embeddings.torch.static\_embedding module +================================================= + +.. automodule:: fastNLP.embeddings.torch.static_embedding + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.embeddings.torch.utils.rst b/docs/source/fastNLP.embeddings.torch.utils.rst new file mode 100644 index 00000000..9d1fc5b5 --- /dev/null +++ b/docs/source/fastNLP.embeddings.torch.utils.rst @@ -0,0 +1,7 @@ +fastNLP.embeddings.torch.utils module +===================================== + +.. automodule:: fastNLP.embeddings.torch.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.models.rst b/docs/source/fastNLP.models.rst new file mode 100644 index 00000000..eaef5a5e --- /dev/null +++ b/docs/source/fastNLP.models.rst @@ -0,0 +1,15 @@ +fastNLP.models package +====================== + +.. automodule:: fastNLP.models + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.models.torch diff --git a/docs/source/fastNLP.models.torch.biaffine_parser.rst b/docs/source/fastNLP.models.torch.biaffine_parser.rst new file mode 100644 index 00000000..c75d7079 --- /dev/null +++ b/docs/source/fastNLP.models.torch.biaffine_parser.rst @@ -0,0 +1,7 @@ +fastNLP.models.torch.biaffine\_parser module +============================================ + +.. automodule:: fastNLP.models.torch.biaffine_parser + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.models.torch.cnn_text_classification.rst b/docs/source/fastNLP.models.torch.cnn_text_classification.rst new file mode 100644 index 00000000..a0b4e1bd --- /dev/null +++ b/docs/source/fastNLP.models.torch.cnn_text_classification.rst @@ -0,0 +1,7 @@ +fastNLP.models.torch.cnn\_text\_classification module +===================================================== + +.. automodule:: fastNLP.models.torch.cnn_text_classification + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.models.torch.rst b/docs/source/fastNLP.models.torch.rst new file mode 100644 index 00000000..7196f3f7 --- /dev/null +++ b/docs/source/fastNLP.models.torch.rst @@ -0,0 +1,19 @@ +fastNLP.models.torch package +============================ + +.. automodule:: fastNLP.models.torch + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.models.torch.biaffine_parser + fastNLP.models.torch.cnn_text_classification + fastNLP.models.torch.seq2seq_generator + fastNLP.models.torch.seq2seq_model + fastNLP.models.torch.sequence_labeling diff --git a/docs/source/fastNLP.models.torch.seq2seq_generator.rst b/docs/source/fastNLP.models.torch.seq2seq_generator.rst new file mode 100644 index 00000000..bc1e4ca0 --- /dev/null +++ b/docs/source/fastNLP.models.torch.seq2seq_generator.rst @@ -0,0 +1,7 @@ +fastNLP.models.torch.seq2seq\_generator module +============================================== + +.. automodule:: fastNLP.models.torch.seq2seq_generator + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.models.torch.seq2seq_model.rst b/docs/source/fastNLP.models.torch.seq2seq_model.rst new file mode 100644 index 00000000..802b8793 --- /dev/null +++ b/docs/source/fastNLP.models.torch.seq2seq_model.rst @@ -0,0 +1,7 @@ +fastNLP.models.torch.seq2seq\_model module +========================================== + +.. automodule:: fastNLP.models.torch.seq2seq_model + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.models.torch.sequence_labeling.rst b/docs/source/fastNLP.models.torch.sequence_labeling.rst new file mode 100644 index 00000000..af834f53 --- /dev/null +++ b/docs/source/fastNLP.models.torch.sequence_labeling.rst @@ -0,0 +1,7 @@ +fastNLP.models.torch.sequence\_labeling module +============================================== + +.. automodule:: fastNLP.models.torch.sequence_labeling + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.attention.rst b/docs/source/fastNLP.modules.torch.attention.rst new file mode 100644 index 00000000..52b7bf8c --- /dev/null +++ b/docs/source/fastNLP.modules.torch.attention.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.attention module +====================================== + +.. automodule:: fastNLP.modules.torch.attention + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.decoder.crf.rst b/docs/source/fastNLP.modules.torch.decoder.crf.rst new file mode 100644 index 00000000..2d9e3460 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.decoder.crf.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.decoder.crf module +======================================== + +.. automodule:: fastNLP.modules.torch.decoder.crf + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.decoder.mlp.rst b/docs/source/fastNLP.modules.torch.decoder.mlp.rst new file mode 100644 index 00000000..6bb9cc5c --- /dev/null +++ b/docs/source/fastNLP.modules.torch.decoder.mlp.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.decoder.mlp module +======================================== + +.. automodule:: fastNLP.modules.torch.decoder.mlp + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.decoder.rst b/docs/source/fastNLP.modules.torch.decoder.rst new file mode 100644 index 00000000..999ab01d --- /dev/null +++ b/docs/source/fastNLP.modules.torch.decoder.rst @@ -0,0 +1,18 @@ +fastNLP.modules.torch.decoder package +===================================== + +.. automodule:: fastNLP.modules.torch.decoder + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.modules.torch.decoder.crf + fastNLP.modules.torch.decoder.mlp + fastNLP.modules.torch.decoder.seq2seq_decoder + fastNLP.modules.torch.decoder.seq2seq_state diff --git a/docs/source/fastNLP.modules.torch.decoder.seq2seq_decoder.rst b/docs/source/fastNLP.modules.torch.decoder.seq2seq_decoder.rst new file mode 100644 index 00000000..43c77fea --- /dev/null +++ b/docs/source/fastNLP.modules.torch.decoder.seq2seq_decoder.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.decoder.seq2seq\_decoder module +===================================================== + +.. automodule:: fastNLP.modules.torch.decoder.seq2seq_decoder + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.decoder.seq2seq_state.rst b/docs/source/fastNLP.modules.torch.decoder.seq2seq_state.rst new file mode 100644 index 00000000..05f730e4 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.decoder.seq2seq_state.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.decoder.seq2seq\_state module +=================================================== + +.. automodule:: fastNLP.modules.torch.decoder.seq2seq_state + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.dropout.rst b/docs/source/fastNLP.modules.torch.dropout.rst new file mode 100644 index 00000000..8e4b591b --- /dev/null +++ b/docs/source/fastNLP.modules.torch.dropout.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.dropout module +==================================== + +.. automodule:: fastNLP.modules.torch.dropout + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.conv_maxpool.rst b/docs/source/fastNLP.modules.torch.encoder.conv_maxpool.rst new file mode 100644 index 00000000..438ec076 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.conv_maxpool.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.conv\_maxpool module +================================================== + +.. automodule:: fastNLP.modules.torch.encoder.conv_maxpool + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.lstm.rst b/docs/source/fastNLP.modules.torch.encoder.lstm.rst new file mode 100644 index 00000000..918e13cb --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.lstm.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.lstm module +========================================= + +.. automodule:: fastNLP.modules.torch.encoder.lstm + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.rst b/docs/source/fastNLP.modules.torch.encoder.rst new file mode 100644 index 00000000..14120ed1 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.rst @@ -0,0 +1,20 @@ +fastNLP.modules.torch.encoder package +===================================== + +.. automodule:: fastNLP.modules.torch.encoder + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.modules.torch.encoder.conv_maxpool + fastNLP.modules.torch.encoder.lstm + fastNLP.modules.torch.encoder.seq2seq_encoder + fastNLP.modules.torch.encoder.star_transformer + fastNLP.modules.torch.encoder.transformer + fastNLP.modules.torch.encoder.variational_rnn diff --git a/docs/source/fastNLP.modules.torch.encoder.seq2seq_encoder.rst b/docs/source/fastNLP.modules.torch.encoder.seq2seq_encoder.rst new file mode 100644 index 00000000..152fc091 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.seq2seq_encoder.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.seq2seq\_encoder module +===================================================== + +.. automodule:: fastNLP.modules.torch.encoder.seq2seq_encoder + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.star_transformer.rst b/docs/source/fastNLP.modules.torch.encoder.star_transformer.rst new file mode 100644 index 00000000..3257cf13 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.star_transformer.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.star\_transformer module +====================================================== + +.. automodule:: fastNLP.modules.torch.encoder.star_transformer + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.transformer.rst b/docs/source/fastNLP.modules.torch.encoder.transformer.rst new file mode 100644 index 00000000..0a3c893f --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.transformer.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.transformer module +================================================ + +.. automodule:: fastNLP.modules.torch.encoder.transformer + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.encoder.variational_rnn.rst b/docs/source/fastNLP.modules.torch.encoder.variational_rnn.rst new file mode 100644 index 00000000..71a70c3a --- /dev/null +++ b/docs/source/fastNLP.modules.torch.encoder.variational_rnn.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.encoder.variational\_rnn module +===================================================== + +.. automodule:: fastNLP.modules.torch.encoder.variational_rnn + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.generator.rst b/docs/source/fastNLP.modules.torch.generator.rst new file mode 100644 index 00000000..783db61d --- /dev/null +++ b/docs/source/fastNLP.modules.torch.generator.rst @@ -0,0 +1,15 @@ +fastNLP.modules.torch.generator package +======================================= + +.. automodule:: fastNLP.modules.torch.generator + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.modules.torch.generator.seq2seq_generator diff --git a/docs/source/fastNLP.modules.torch.generator.seq2seq_generator.rst b/docs/source/fastNLP.modules.torch.generator.seq2seq_generator.rst new file mode 100644 index 00000000..4abc102f --- /dev/null +++ b/docs/source/fastNLP.modules.torch.generator.seq2seq_generator.rst @@ -0,0 +1,7 @@ +fastNLP.modules.torch.generator.seq2seq\_generator module +========================================================= + +.. automodule:: fastNLP.modules.torch.generator.seq2seq_generator + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/fastNLP.modules.torch.rst b/docs/source/fastNLP.modules.torch.rst new file mode 100644 index 00000000..8e1fb0f5 --- /dev/null +++ b/docs/source/fastNLP.modules.torch.rst @@ -0,0 +1,26 @@ +fastNLP.modules.torch package +============================= + +.. automodule:: fastNLP.modules.torch + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.modules.torch.decoder + fastNLP.modules.torch.encoder + fastNLP.modules.torch.generator + +Submodules +---------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.modules.torch.attention + fastNLP.modules.torch.dropout diff --git a/docs/source/fastNLP.transformers.rst b/docs/source/fastNLP.transformers.rst new file mode 100644 index 00000000..c681acca --- /dev/null +++ b/docs/source/fastNLP.transformers.rst @@ -0,0 +1,15 @@ +fastNLP.transformers package +======================= + +.. automodule:: fastNLP.transformers + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + fastNLP.transformers.torch diff --git a/docs/source/fastNLP.transformers.torch.rst b/docs/source/fastNLP.transformers.torch.rst new file mode 100644 index 00000000..ab6ef210 --- /dev/null +++ b/docs/source/fastNLP.transformers.torch.rst @@ -0,0 +1,7 @@ +fastNLP.transformers.torch package +======================= + +.. automodule:: fastNLP.transformers.torch + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/index.rst b/docs/source/index.rst index 10b0d74c..abe73d8a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,18 +2,18 @@ fastNLP 中文文档 ===================== -用户手册 +快速上手 ---------------- .. toctree:: - :maxdepth: 1 + :maxdepth: 2 - 语法样例 + tutorials API 文档 ------------- -除了用户手册之外,你还可以通过查阅 API 文档来找到你所需要的工具。 +您可以通过查阅 API 文档来找到你所需要的工具。 .. toctree:: :titlesonly: diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst new file mode 100644 index 00000000..bc32d10f --- /dev/null +++ b/docs/source/tutorials.rst @@ -0,0 +1,8 @@ +fastNLP 教程系列 +================ + +.. toctree:: + :maxdepth: 1 + :glob: + + tutorials/* From 48688f1c928fe01d9c7b90eb09cac4dccf22c89c Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:27:22 +0000 Subject: [PATCH 03/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84rst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/fastNLP.core.dataloaders.mix_dataloader.rst | 7 ------- ...fastNLP.core.drivers.torch_driver.fairscale_sharded.rst | 7 ------- docs/source/fastNLP.io.model_io.rst | 7 ------- docs/source/fastNLP.io.pipe.coreference.rst | 7 ------- 4 files changed, 28 deletions(-) delete mode 100644 docs/source/fastNLP.core.dataloaders.mix_dataloader.rst delete mode 100644 docs/source/fastNLP.core.drivers.torch_driver.fairscale_sharded.rst delete mode 100644 docs/source/fastNLP.io.model_io.rst delete mode 100644 docs/source/fastNLP.io.pipe.coreference.rst diff --git a/docs/source/fastNLP.core.dataloaders.mix_dataloader.rst b/docs/source/fastNLP.core.dataloaders.mix_dataloader.rst deleted file mode 100644 index d2ffa234..00000000 --- a/docs/source/fastNLP.core.dataloaders.mix_dataloader.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.core.dataloaders.mix\_dataloader module -=============================================== - -.. automodule:: fastNLP.core.dataloaders.mix_dataloader - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/fastNLP.core.drivers.torch_driver.fairscale_sharded.rst b/docs/source/fastNLP.core.drivers.torch_driver.fairscale_sharded.rst deleted file mode 100644 index 765ac4ae..00000000 --- a/docs/source/fastNLP.core.drivers.torch_driver.fairscale_sharded.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.core.drivers.torch\_driver.fairscale\_sharded module -============================================================ - -.. automodule:: fastNLP.core.drivers.torch_driver.fairscale_sharded - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/fastNLP.io.model_io.rst b/docs/source/fastNLP.io.model_io.rst deleted file mode 100644 index fe13d1d7..00000000 --- a/docs/source/fastNLP.io.model_io.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.io.model\_io module -=========================== - -.. automodule:: fastNLP.io.model_io - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/fastNLP.io.pipe.coreference.rst b/docs/source/fastNLP.io.pipe.coreference.rst deleted file mode 100644 index bccdb0a7..00000000 --- a/docs/source/fastNLP.io.pipe.coreference.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.io.pipe.coreference module -================================== - -.. automodule:: fastNLP.io.pipe.coreference - :members: - :undoc-members: - :show-inheritance: From 2a31cf831fda900162c3c6d1eb002a0bbcce9d17 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:29:57 +0000 Subject: [PATCH 04/14] =?UTF-8?q?=E5=85=B6=E5=AE=83=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../source/tutorials/fastnlp_tutorial_0.ipynb | 1352 +++++++++ .../source/tutorials/fastnlp_tutorial_1.ipynb | 1333 +++++++++ .../source/tutorials/fastnlp_tutorial_2.ipynb | 884 ++++++ .../source/tutorials/fastnlp_tutorial_3.ipynb | 621 ++++ .../source/tutorials/fastnlp_tutorial_4.ipynb | 2614 +++++++++++++++++ .../source/tutorials/fastnlp_tutorial_5.ipynb | 1242 ++++++++ .../source/tutorials/fastnlp_tutorial_6.ipynb | 1646 +++++++++++ .../tutorials/fastnlp_tutorial_e1.ipynb | 1280 ++++++++ .../tutorials/fastnlp_tutorial_e2.ipynb | 1082 +++++++ .../fastnlp_tutorial_paddle_e1.ipynb | 1086 +++++++ .../fastnlp_tutorial_paddle_e2.ipynb | 1510 ++++++++++ .../figures/E1-fig-glue-benchmark.png | Bin 0 -> 158817 bytes .../figures/E2-fig-p-tuning-v2-model.png | Bin 0 -> 50517 bytes .../tutorials/figures/E2-fig-pet-model.png | Bin 0 -> 57162 bytes .../figures/T0-fig-parameter-matching.png | Bin 0 -> 95584 bytes .../figures/T0-fig-trainer-and-evaluator.png | Bin 0 -> 71418 bytes .../figures/T0-fig-training-structure.png | Bin 0 -> 80296 bytes .../figures/T1-fig-dataset-and-vocabulary.png | Bin 0 -> 138905 bytes .../paddle-ernie-1.0-masking-levels.png | Bin 0 -> 59022 bytes .../figures/paddle-ernie-1.0-masking.png | Bin 0 -> 46898 bytes .../paddle-ernie-2.0-continual-pretrain.png | Bin 0 -> 128680 bytes .../figures/paddle-ernie-3.0-framework.png | Bin 0 -> 202018 bytes fastNLP/__init__.py | 2 +- .../core/collators/padders/oneflow_padder.py | 1 + fastNLP/core/controllers/trainer.py | 14 +- fastNLP/core/dataset/dataset.py | 11 +- .../core/drivers/torch_driver/torch_fsdp.py | 10 +- fastNLP/embeddings/torch/static_embedding.py | 2 +- fastNLP/transformers/__init__.py | 1 - 29 files changed, 14671 insertions(+), 20 deletions(-) create mode 100644 docs/source/tutorials/fastnlp_tutorial_0.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_1.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_2.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_3.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_4.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_5.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_6.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_e1.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_e2.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_paddle_e1.ipynb create mode 100644 docs/source/tutorials/fastnlp_tutorial_paddle_e2.ipynb create mode 100644 docs/source/tutorials/figures/E1-fig-glue-benchmark.png create mode 100644 docs/source/tutorials/figures/E2-fig-p-tuning-v2-model.png create mode 100644 docs/source/tutorials/figures/E2-fig-pet-model.png create mode 100644 docs/source/tutorials/figures/T0-fig-parameter-matching.png create mode 100644 docs/source/tutorials/figures/T0-fig-trainer-and-evaluator.png create mode 100644 docs/source/tutorials/figures/T0-fig-training-structure.png create mode 100644 docs/source/tutorials/figures/T1-fig-dataset-and-vocabulary.png create mode 100644 docs/source/tutorials/figures/paddle-ernie-1.0-masking-levels.png create mode 100644 docs/source/tutorials/figures/paddle-ernie-1.0-masking.png create mode 100644 docs/source/tutorials/figures/paddle-ernie-2.0-continual-pretrain.png create mode 100644 docs/source/tutorials/figures/paddle-ernie-3.0-framework.png diff --git a/docs/source/tutorials/fastnlp_tutorial_0.ipynb b/docs/source/tutorials/fastnlp_tutorial_0.ipynb new file mode 100644 index 00000000..09667794 --- /dev/null +++ b/docs/source/tutorials/fastnlp_tutorial_0.ipynb @@ -0,0 +1,1352 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "aec0fde7", + "metadata": {}, + "source": [ + "# T0. trainer 和 evaluator 的基本使用\n", + "\n", + "  1   trainer 和 evaluator 的基本关系\n", + " \n", + "    1.1   trainer 和 evaluater 的初始化\n", + "\n", + "    1.2   driver 的含义与使用要求\n", + "\n", + "    1.3   trainer 内部初始化 evaluater\n", + "\n", + "  2   使用 fastNLP 搭建 argmax 模型\n", + "\n", + "    2.1   trainer_step 和 evaluator_step\n", + "\n", + "    2.2   trainer 和 evaluator 的参数匹配\n", + "\n", + "    2.3   示例:argmax 模型的搭建\n", + "\n", + "  3   使用 fastNLP 训练 argmax 模型\n", + " \n", + "    3.1   trainer 外部初始化的 evaluator\n", + "\n", + "    3.2   trainer 内部初始化的 evaluator " + ] + }, + { + "cell_type": "markdown", + "id": "09ea669a", + "metadata": {}, + "source": [ + "## 1. trainer 和 evaluator 的基本关系\n", + "\n", + "### 1.1 trainer 和 evaluator 的初始化\n", + "\n", + "在`fastNLP 1.0`中,`Trainer`模块和`Evaluator`模块分别表示 **“训练器”和“评测器”**\n", + "\n", + "  对应于之前的`fastNLP`版本中的`Trainer`模块和`Tester`模块,其定义方法如下所示\n", + "\n", + "在`fastNLP 1.0`中,需要注意,在同个`python`脚本中先使用`Trainer`训练,然后使用`Evaluator`评测\n", + "\n", + "  非常关键的问题在于**如何正确设置二者的 driver**。这就引入了另一个问题:什么是 `driver`?\n", + "\n", + "\n", + "```python\n", + "trainer = Trainer(\n", + " model=model, # 模型基于 torch.nn.Module\n", + " train_dataloader=train_dataloader, # 加载模块基于 torch.utils.data.DataLoader \n", + " optimizers=optimizer, # 优化模块基于 torch.optim.*\n", + " ...\n", + " driver=\"torch\", # 使用 pytorch 模块进行训练 \n", + " device='cuda', # 使用 GPU:0 显卡执行训练\n", + " ...\n", + " )\n", + "...\n", + "evaluator = Evaluator(\n", + " model=model, # 模型基于 torch.nn.Module\n", + " dataloaders=evaluate_dataloader, # 加载模块基于 torch.utils.data.DataLoader\n", + " metrics={'acc': Accuracy()}, # 测评方法使用 fastNLP.core.metrics.Accuracy \n", + " ...\n", + " driver=trainer.driver, # 保持同 trainer 的 driver 一致\n", + " device=None,\n", + " ...\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "3c11fe1a", + "metadata": {}, + "source": [ + "### 1.2 driver 的含义与使用要求\n", + "\n", + "在`fastNLP 1.0`中,**driver**这一概念被用来表示**控制具体训练的各个步骤的最终执行部分**\n", + "\n", + "  例如神经网络前向、后向传播的具体执行、网络参数的优化和数据在设备间的迁移等\n", + "\n", + "在`fastNLP 1.0`中,**Trainer 和 Evaluator 都依赖于具体的 driver 来完成整体的工作流程**\n", + "\n", + "  具体`driver`与`Trainer`以及`Evaluator`之间的关系之后`tutorial 4`中的详细介绍\n", + "\n", + "注:这里给出一条建议:**在同一脚本中**,**所有的** Trainer **和** Evaluator **使用的** driver **应当保持一致**\n", + "\n", + "  尽量不出现,之前使用单卡的`driver`,后面又使用多卡的`driver`,这是因为,当脚本执行至\n", + "\n", + "  多卡`driver`处时,会重启一个进程执行之前所有内容,如此一来可能会造成一些意想不到的麻烦" + ] + }, + { + "cell_type": "markdown", + "id": "2cac4a1a", + "metadata": {}, + "source": [ + "### 1.3 Trainer 内部初始化 Evaluator\n", + "\n", + "在`fastNLP 1.0`中,如果在**初始化 Trainer 时**,**传入参数 evaluator_dataloaders 和 metrics **\n", + "\n", + "  则在`Trainer`内部,也会初始化单独的`Evaluator`来帮助训练过程中对验证集的评测\n", + "\n", + "```python\n", + "trainer = Trainer(\n", + " model=model,\n", + " train_dataloader=train_dataloader,\n", + " optimizers=optimizer,\n", + " ...\n", + " driver=\"torch\",\n", + " device='cuda',\n", + " ...\n", + " evaluate_dataloaders=evaluate_dataloader, # 传入参数 evaluator_dataloaders\n", + " metrics={'acc': Accuracy()}, # 传入参数 metrics\n", + " ...\n", + " )\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "0c9c7dda", + "metadata": {}, + "source": [ + "## 2. argmax 模型的搭建实例" + ] + }, + { + "cell_type": "markdown", + "id": "524ac200", + "metadata": {}, + "source": [ + "### 2.1 trainer_step 和 evaluator_step\n", + "\n", + "在`fastNLP 1.0`中,使用`pytorch.nn.Module`搭建需要训练的模型,在搭建模型过程中,除了\n", + "\n", + "  添加`pytorch`要求的`forward`方法外,还需要添加 `train_step` 和 `evaluate_step` 这两个方法\n", + "\n", + "```python\n", + "class Model(torch.nn.Module):\n", + " def __init__(self):\n", + " super(Model, self).__init__()\n", + " self.loss_fn = torch.nn.CrossEntropyLoss()\n", + " pass\n", + "\n", + " def forward(self, x):\n", + " pass\n", + "\n", + " def train_step(self, x, y):\n", + " pred = self(x)\n", + " return {\"loss\": self.loss_fn(pred, y)}\n", + "\n", + " def evaluate_step(self, x, y):\n", + " pred = self(x)\n", + " pred = torch.max(pred, dim=-1)[1]\n", + " return {\"pred\": pred, \"target\": y}\n", + "```\n", + "***\n", + "在`fastNLP 1.0`中,**函数 train_step 是 Trainer 中参数 train_fn 的默认值**\n", + "\n", + "  由于,在`Trainer`训练时,**Trainer 通过参数 train_fn 对应的模型方法获得当前数据批次的损失值**\n", + "\n", + "  因此,在`Trainer`训练时,`Trainer`首先会寻找模型是否定义了`train_step`这一方法\n", + "\n", + "    如果没有找到,那么`Trainer`会默认使用模型的`forward`函数来进行训练的前向传播过程\n", + "\n", + "注:在`fastNLP 1.0`中,**Trainer 要求模型通过 train_step 来返回一个字典**,**满足如 {\"loss\": loss} 的形式**\n", + "\n", + "  此外,这里也可以通过传入`Trainer`的参数`output_mapping`来实现输出的转换,详见(trainer的详细讲解,待补充)\n", + "\n", + "同样,在`fastNLP 1.0`中,**函数 evaluate_step 是 Evaluator 中参数 evaluate_fn 的默认值**\n", + "\n", + "  在`Evaluator`测试时,**Evaluator 通过参数 evaluate_fn 对应的模型方法获得当前数据批次的评测结果**\n", + "\n", + "  从用户角度,模型通过`evaluate_step`方法来返回一个字典,内容与传入`Evaluator`的`metrics`一致\n", + "\n", + "  从模块角度,该字典的键值和`metric`中的`update`函数的签名一致,这样的机制在传参时被称为“**参数匹配**”\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "id": "fb3272eb", + "metadata": {}, + "source": [ + "### 2.2 trainer 和 evaluator 的参数匹配\n", + "\n", + "在`fastNLP 1.0`中,参数匹配涉及到两个方面,分别是在\n", + "\n", + "  一方面,**在模型的前向传播中**,**dataloader 向 train_step 或 evaluate_step 函数传递 batch**\n", + "\n", + "  另方面,**在模型的评测过程中**,**evaluate_dataloader 向 metric 的 update 函数传递 batch**\n", + "\n", + "对于前者,在`Trainer`和`Evaluator`中的参数`model_wo_auto_param_call`被设置为`False`时\n", + "\n", + "    **fastNLP 1.0 要求 dataloader 生成的每个 batch **,**满足如 {\"x\": x, \"y\": y} 的形式**\n", + "\n", + "  同时,`fastNLP 1.0`会查看模型的`train_step`和`evaluate_step`方法的参数签名,并为对应参数传入对应数值\n", + "\n", + "    **字典形式的定义**,**对应在 Dataset 定义的 \\_\\_getitem\\_\\_ 方法中**,例如下方的`ArgMaxDatset`\n", + "\n", + "  而在`Trainer`和`Evaluator`中的参数`model_wo_auto_param_call`被设置为`True`时\n", + "\n", + "    `fastNLP 1.0`会将`batch`直接传给模型的`train_step`、`evaluate_step`或`forward`函数\n", + "\n", + "```python\n", + "class Dataset(torch.utils.data.Dataset):\n", + " def __init__(self, x, y):\n", + " self.x = x\n", + " self.y = y\n", + "\n", + " def __len__(self):\n", + " return len(self.x)\n", + "\n", + " def __getitem__(self, item):\n", + " return {\"x\": self.x[item], \"y\": self.y[item]}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "f5f1a6aa", + "metadata": {}, + "source": [ + "对于后者,首先要明确,在`Trainer`和`Evaluator`中,`metrics`的计算分为`update`和`get_metric`两步\n", + "\n", + "    **update 函数**,**针对一个 batch 的预测结果**,计算其累计的评价指标\n", + "\n", + "    **get_metric 函数**,**统计 update 函数累计的评价指标**,来计算最终的评价结果\n", + "\n", + "  例如对于`Accuracy`来说,`update`函数会更新一个`batch`的正例数量`right_num`和负例数量`total_num`\n", + "\n", + "    而`get_metric`函数则会返回所有`batch`的评测值`right_num / total_num`\n", + "\n", + "  在此基础上,**fastNLP 1.0 要求 evaluate_dataloader 生成的每个 batch 传递给对应的 metric**\n", + "\n", + "    **以 {\"pred\": y_pred, \"target\": y_true} 的形式**,对应其`update`函数的函数签名\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "id": "f62b7bb1", + "metadata": {}, + "source": [ + "### 2.3 示例:argmax 模型的搭建\n", + "\n", + "下文将通过训练`argmax`模型,简单介绍如何`Trainer`模块的使用方式\n", + "\n", + "  首先,使用`pytorch.nn.Module`定义`argmax`模型,目标是输入一组固定维度的向量,输出其中数值最大的数的索引" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5314482b", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "\n", + "class ArgMaxModel(nn.Module):\n", + " def __init__(self, num_labels, feature_dimension):\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", + " self.ac1 = nn.ReLU()\n", + " self.linear2 = nn.Linear(in_features=10, out_features=10)\n", + " self.ac2 = nn.ReLU()\n", + " self.output = nn.Linear(in_features=10, out_features=num_labels)\n", + " self.loss_fn = nn.CrossEntropyLoss()\n", + "\n", + " def forward(self, x):\n", + " pred = self.ac1(self.linear1(x))\n", + " pred = self.ac2(self.linear2(pred))\n", + " pred = self.output(pred)\n", + " return pred\n", + "\n", + " def train_step(self, x, y):\n", + " pred = self(x)\n", + " return {\"loss\": self.loss_fn(pred, y)}\n", + "\n", + " def evaluate_step(self, x, y):\n", + " pred = self(x)\n", + " pred = torch.max(pred, dim=-1)[1]\n", + " return {\"pred\": pred, \"target\": y}" + ] + }, + { + "cell_type": "markdown", + "id": "71f3fa6b", + "metadata": {}, + "source": [ + "  接着,使用`torch.utils.data.Dataset`定义`ArgMaxDataset`数据集\n", + "\n", + "    数据集包含三个参数:维度`feature_dimension`、数据量`data_num`和随机种子`seed`\n", + "\n", + "    数据及初始化是,自动生成指定维度的向量,并为每个向量标注出其中最大值的索引作为预测标签" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fe612e61", + "metadata": { + "pycharm": { + "is_executing": false + } + }, + "outputs": [], + "source": [ + "from torch.utils.data import Dataset\n", + "\n", + "class ArgMaxDataset(Dataset):\n", + " def __init__(self, feature_dimension, data_num=1000, seed=0):\n", + " self.num_labels = feature_dimension\n", + " self.feature_dimension = feature_dimension\n", + " self.data_num = data_num\n", + " self.seed = seed\n", + "\n", + " g = torch.Generator()\n", + " g.manual_seed(1000)\n", + " self.x = torch.randint(low=-100, high=100, size=[data_num, feature_dimension], generator=g).float()\n", + " self.y = torch.max(self.x, dim=-1)[1]\n", + "\n", + " def __len__(self):\n", + " return self.data_num\n", + "\n", + " def __getitem__(self, item):\n", + " return {\"x\": self.x[item], \"y\": self.y[item]}" + ] + }, + { + "cell_type": "markdown", + "id": "2cb96332", + "metadata": {}, + "source": [ + "  然后,根据`ArgMaxModel`类初始化模型实例,保持输入维度`feature_dimension`和输出标签数量`num_labels`一致\n", + "\n", + "    再根据`ArgMaxDataset`类初始化两个数据集实例,分别用来模型测试和模型评测,数据量各1000笔" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "76172ef8", + "metadata": { + "pycharm": { + "is_executing": false + } + }, + "outputs": [], + "source": [ + "model = ArgMaxModel(num_labels=10, feature_dimension=10)\n", + "\n", + "train_dataset = ArgMaxDataset(feature_dimension=10, data_num=1000)\n", + "evaluate_dataset = ArgMaxDataset(feature_dimension=10, data_num=100)" + ] + }, + { + "cell_type": "markdown", + "id": "4e7d25ee", + "metadata": {}, + "source": [ + "  此外,使用`torch.utils.data.DataLoader`初始化两个数据加载模块,批量大小同为8,分别用于训练和测评" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "363b5b09", + "metadata": {}, + "outputs": [], + "source": [ + "from torch.utils.data import DataLoader\n", + "\n", + "train_dataloader = DataLoader(train_dataset, batch_size=8, shuffle=True)\n", + "evaluate_dataloader = DataLoader(evaluate_dataset, batch_size=8)" + ] + }, + { + "cell_type": "markdown", + "id": "c8d4443f", + "metadata": {}, + "source": [ + "  最后,使用`torch.optim.SGD`初始化一个优化模块,基于随机梯度下降法" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "dc28a2d9", + "metadata": { + "pycharm": { + "is_executing": false + } + }, + "outputs": [], + "source": [ + "from torch.optim import SGD\n", + "\n", + "optimizer = SGD(model.parameters(), lr=0.001)" + ] + }, + { + "cell_type": "markdown", + "id": "eb8ca6cf", + "metadata": {}, + "source": [ + "## 3. 使用 fastNLP 1.0 训练 argmax 模型\n", + "\n", + "### 3.1 trainer 外部初始化的 evaluator" + ] + }, + { + "cell_type": "markdown", + "id": "55145553", + "metadata": {}, + "source": [ + "通过从`fastNLP`库中导入`Trainer`类,初始化`trainer`实例,对模型进行训练\n", + "\n", + "  需要导入预先定义好的模型`model`、对应的数据加载模块`train_dataloader`、优化模块`optimizer`\n", + "\n", + "  通过`progress_bar`设定进度条格式,默认为`\"auto\"`,此外还有`\"rich\"`、`\"raw\"`和`None`\n", + "\n", + "    但对于`\"auto\"`和`\"rich\"`格式,在`jupyter`中,进度条会在训练结束后会被丢弃\n", + "\n", + "  通过`n_epochs`设定优化迭代轮数,默认为20;全部`Trainer`的全部变量与函数可以通过`dir(trainer)`查询" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b51b7a2d", + "metadata": { + "pycharm": { + "is_executing": false + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "\n", + "from fastNLP import Trainer\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " driver=\"torch\",\n", + " device='cuda',\n", + " train_dataloader=train_dataloader,\n", + " optimizers=optimizer,\n", + " n_epochs=10, # 设定迭代轮数 \n", + " progress_bar=\"auto\" # 设定进度条格式\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "6e202d6e", + "metadata": {}, + "source": [ + "通过使用`Trainer`类的`run`函数,进行训练\n", + "\n", + "  其中,可以通过参数`num_train_batch_per_epoch`决定每个`epoch`运行多少个`batch`后停止,默认全部\n", + "\n", + "  `run`函数完成后在`jupyter`中没有输出保留,此外,通过`help(trainer.run)`可以查询`run`函数的详细内容" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ba047ead", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "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/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "trainer.run()" + ] + }, + { + "cell_type": "markdown", + "id": "c16c5fa4", + "metadata": {}, + "source": [ + "通过从`fastNLP`库中导入`Evaluator`类,初始化`evaluator`实例,对模型进行评测\n", + "\n", + "  需要导入预先定义好的模型`model`、对应的数据加载模块`evaluate_dataloader`\n", + "\n", + "  需要注意的是评测方法`metrics`,设定为形如`{'acc': fastNLP.core.metrics.Accuracy()}`的字典\n", + "\n", + "  类似地,也可以通过`progress_bar`限定进度条格式,默认为`\"auto\"`" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1c6b6b36", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "outputs": [], + "source": [ + "from fastNLP import Evaluator\n", + "from fastNLP import Accuracy\n", + "\n", + "evaluator = Evaluator(\n", + " model=model,\n", + " driver=trainer.driver, # 需要使用 trainer 已经启动的 driver\n", + " device=None,\n", + " dataloaders=evaluate_dataloader,\n", + " metrics={'acc': Accuracy()} # 需要严格使用此种形式的字典\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8157bb9b", + "metadata": {}, + "source": [ + "通过使用`Evaluator`类的`run`函数,进行训练\n", + "\n", + "  其中,可以通过参数`num_eval_batch_per_dl`决定每个`evaluate_dataloader`运行多少个`batch`停止,默认全部\n", + "\n", + "  最终,输出形如`{'acc#acc': acc}`的字典,在`jupyter`中,进度条会在评测结束后会被丢弃" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "f7cb0165", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "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/html": [
+       "
{'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.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": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "{'acc#acc': 0.31, 'total#acc': 100.0, 'correct#acc': 31.0}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "evaluator.run()" + ] + }, + { + "cell_type": "markdown", + "id": "dd9f68fa", + "metadata": {}, + "source": [ + "### 3.2 trainer 内部初始化的 evaluator \n", + "\n", + "通过在初始化`trainer`实例时加入`evaluate_dataloaders`和`metrics`,可以实现在训练过程中进行评测\n", + "\n", + "  通过`progress_bar`同时设定训练和评估进度条格式,在`jupyter`中,在进度条训练结束后会被丢弃\n", + "\n", + "  但是中间的评估结果仍会保留;**通过 evaluate_every 设定评估频率**,可以为负数、正数或者函数:\n", + "\n", + "    **为负数时**,**表示每隔几个 epoch 评估一次**;**为正数时**,**则表示每隔几个 batch 评估一次**" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "183c7d19", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "outputs": [], + "source": [ + "trainer = Trainer(\n", + " model=model,\n", + " driver=trainer.driver, # 因为是在同个脚本中,这里的 driver 同样需要重用\n", + " train_dataloader=train_dataloader,\n", + " evaluate_dataloaders=evaluate_dataloader,\n", + " metrics={'acc': Accuracy()},\n", + " optimizers=optimizer,\n", + " n_epochs=10, \n", + " evaluate_every=-1, # 表示每个 epoch 的结束进行评估\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "714cc404", + "metadata": {}, + "source": [ + "通过使用`Trainer`类的`run`函数,进行训练\n", + "\n", + "  还可以通过**参数 num_eval_sanity_batch 决定每次训练前运行多少个 evaluate_batch 进行评测**,**默认为 2 **\n", + "\n", + "  之所以“先评测后训练”,是为了保证训练很长时间的数据,不会在评测阶段出问题,故作此**试探性评测**" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2e4daa2c", + "metadata": { + "pycharm": { + "is_executing": true + } + }, + "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": [ + "
\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.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": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "trainer.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "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": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "{'acc#acc': 0.4, 'total#acc': 100.0, 'correct#acc': 40.0}"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "1bc7cb4a",
+   "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"
+  },
+  "pycharm": {
+   "stem_cell": {
+    "cell_type": "raw",
+    "metadata": {
+     "collapsed": false
+    },
+    "source": []
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/source/tutorials/fastnlp_tutorial_1.ipynb b/docs/source/tutorials/fastnlp_tutorial_1.ipynb
new file mode 100644
index 00000000..cff81a21
--- /dev/null
+++ b/docs/source/tutorials/fastnlp_tutorial_1.ipynb
@@ -0,0 +1,1333 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "cdc25fcd",
+   "metadata": {},
+   "source": [
+    "# T1. dataset 和 vocabulary 的基本使用\n",
+    "\n",
+    "  1   dataset 的使用与结构\n",
+    " \n",
+    "    1.1   dataset 的结构与创建\n",
+    "\n",
+    "    1.2   dataset 的数据预处理\n",
+    "\n",
+    "    1.3   延伸:instance 和 field\n",
+    "\n",
+    "  2   vocabulary 的结构与使用\n",
+    "\n",
+    "    2.1   vocabulary 的创建与修改\n",
+    "\n",
+    "    2.2   vocabulary 与 OOV 问题\n",
+    "\n",
+    "  3   dataset 和 vocabulary 的组合使用\n",
+    " \n",
+    "    3.1   从 dataframe 中加载 dataset\n",
+    "\n",
+    "    3.2   从 dataset 中获取 vocabulary"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0eb18a22",
+   "metadata": {},
+   "source": [
+    "## 1. dataset 的基本使用\n",
+    "\n",
+    "### 1.1  dataset 的结构与创建\n",
+    "\n",
+    "在`fastNLP 1.0`中,使用`DataSet`模块表示数据集,**dataset 类似于关系型数据库中的数据表**(下文统一为小写 `dataset`)\n",
+    "\n",
+    "  **主要包含 field 字段和 instance 实例两个元素**,对应 table 中的 field 字段和`record`记录\n",
+    "\n",
+    "在`fastNLP 1.0`中,`DataSet`模块被定义在`fastNLP.core.dataset`路径下,导入该模块后,最简单的\n",
+    "\n",
+    "  初始化方法,即将字典形式的表格 **{'field1': column1, 'field2': column2, ...}** 传入构造函数"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "a1d69ad2",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+-----+------------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+------------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 1 | I like apples . | ['I', 'like', 'appl... | 4 |\n", + "| 2 | Apples are good for... | ['Apples', 'are', '... | 7 |\n", + "+-----+------------------------+------------------------+-----+\n" + ] + } + ], + "source": [ + "from fastNLP import DataSet\n", + "\n", + "data = {'idx': [0, 1, 2], \n", + " 'sentence':[\"This is an apple .\", \"I like apples .\", \"Apples are good for our health .\"],\n", + " 'words': [['This', 'is', 'an', 'apple', '.'], \n", + " ['I', 'like', 'apples', '.'], \n", + " ['Apples', 'are', 'good', 'for', 'our', 'health', '.']],\n", + " 'num': [5, 4, 7]}\n", + "\n", + "dataset = DataSet(data)\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "9260fdc6", + "metadata": {}, + "source": [ + "  在`dataset`的实例中,字段`field`的名称和实例`instance`中的字符串也可以中文" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3d72ef00", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+------+--------------------+------------------------+------+\n", + "| 序号 | 句子 | 字符 | 长度 |\n", + "+------+--------------------+------------------------+------+\n", + "| 0 | 生活就像海洋, | ['生', '活', '就', ... | 7 |\n", + "| 1 | 只有意志坚强的人, | ['只', '有', '意', ... | 9 |\n", + "| 2 | 才能到达彼岸。 | ['才', '能', '到', ... | 7 |\n", + "+------+--------------------+------------------------+------+\n" + ] + } + ], + "source": [ + "temp = {'序号': [0, 1, 2], \n", + " '句子':[\"生活就像海洋,\", \"只有意志坚强的人,\", \"才能到达彼岸。\"],\n", + " '字符': [['生', '活', '就', '像', '海', '洋', ','], \n", + " ['只', '有', '意', '志', '坚', '强', '的', '人', ','], \n", + " ['才', '能', '到', '达', '彼', '岸', '。']],\n", + " '长度': [7, 9, 7]}\n", + "\n", + "chinese = DataSet(temp)\n", + "print(chinese)" + ] + }, + { + "cell_type": "markdown", + "id": "202e5490", + "metadata": {}, + "source": [ + "在`dataset`中,使用`drop`方法可以删除满足条件的实例,这里使用了python中的`lambda`表达式\n", + "\n", + "  注一:在`drop`方法中,通过设置`inplace`参数将删除对应实例后的`dataset`作为一个新的实例生成" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "09b478f8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2492313174344 2491986424200\n", + "+-----+------------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+------------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 2 | Apples are good for... | ['Apples', 'are', '... | 7 |\n", + "+-----+------------------------+------------------------+-----+\n", + "+-----+------------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+------------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 1 | I like apples . | ['I', 'like', 'appl... | 4 |\n", + "| 2 | Apples are good for... | ['Apples', 'are', '... | 7 |\n", + "+-----+------------------------+------------------------+-----+\n" + ] + } + ], + "source": [ + "dropped = dataset\n", + "dropped = dropped.drop(lambda ins:ins['num'] < 5, inplace=False)\n", + "print(id(dropped), id(dataset))\n", + "print(dropped)\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "aa277674", + "metadata": {}, + "source": [ + "  注二:**对对象使用等号一般表示传引用**,所以对`dataset`使用等号,是传引用而不是赋值\n", + "\n", + "    如下所示,**dropped 和 dataset 具有相同 id**,**对 dropped 执行删除操作 dataset 同时会被修改**" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "77c8583a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2491986424200 2491986424200\n", + "+-----+------------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+------------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 2 | Apples are good for... | ['Apples', 'are', '... | 7 |\n", + "+-----+------------------------+------------------------+-----+\n", + "+-----+------------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+------------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 2 | Apples are good for... | ['Apples', 'are', '... | 7 |\n", + "+-----+------------------------+------------------------+-----+\n" + ] + } + ], + "source": [ + "dropped = dataset\n", + "dropped.drop(lambda ins:ins['num'] < 5)\n", + "print(id(dropped), id(dataset))\n", + "print(dropped)\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "a76199dc", + "metadata": {}, + "source": [ + "在`dataset`中,使用`delet_instance`方法可以删除对应序号的`instance`实例,序号从0开始" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "d8824b40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+-----+--------------------+------------------------+-----+\n", + "| idx | sentence | words | num |\n", + "+-----+--------------------+------------------------+-----+\n", + "| 0 | This is an apple . | ['This', 'is', 'an'... | 5 |\n", + "| 1 | I like apples . | ['I', 'like', 'appl... | 4 |\n", + "+-----+--------------------+------------------------+-----+\n" + ] + } + ], + "source": [ + "dataset = DataSet(data)\n", + "dataset.delete_instance(2)\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "f4fa9f33", + "metadata": {}, + "source": [ + "在`dataset`中,使用`delet_field`方法可以删除对应名称的`field`字段" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f68ddb40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+-----+--------------------+------------------------------+\n", + "| idx | sentence | words |\n", + "+-----+--------------------+------------------------------+\n", + "| 0 | This is an apple . | ['This', 'is', 'an', 'app... |\n", + "| 1 | I like apples . | ['I', 'like', 'apples', '... |\n", + "+-----+--------------------+------------------------------+\n" + ] + } + ], + "source": [ + "dataset.delete_field('num')\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "b1e9d42c", + "metadata": {}, + "source": [ + "### 1.2 dataset 的数据预处理\n", + "\n", + "在`dataset`模块中,`apply`、`apply_field`、`apply_more`和`apply_field_more`函数可以进行简单的数据预处理\n", + "\n", + "  **apply 和 apply_more 输入整条实例**,**apply_field 和 apply_field_more 仅输入实例的部分字段**\n", + "\n", + "  **apply 和 apply_field 仅输出单个字段**,**apply_more 和 apply_field_more 则是输出多个字段**\n", + "\n", + "  **apply 和 apply_field 返回的是个列表**,**apply_more 和 apply_field_more 返回的是个字典**\n", + "\n", + "    预处理过程中,通过`progress_bar`参数设置显示进度条类型,通过`num_proc`设置多进程\n", + "***\n", + "\n", + "`apply`的参数包括一个函数`func`和一个新字段名`new_field_name`,函数`func`的处理对象是`dataset`模块中\n", + "\n", + "  的每个`instance`实例,函数`func`的处理结果存放在`new_field_name`对应的新建字段内" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "72a0b5f9", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Processing: 0%| | 0/3 [00:00,\n", + " 'words': ,\n", + " 'num': }" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset.get_all_fields()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "5433815c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['num', 'sentence', 'words']" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset.get_field_names()" + ] + }, + { + "cell_type": "markdown", + "id": "4964eeed", + "metadata": {}, + "source": [ + "其他`dataset`的基本使用:通过`in`或者`has_field`方法可以判断`dataset`的是否包含某种字段\n", + "\n", + "  通过`rename_field`方法可以更改`dataset`中的字段名称;通过`concat`方法可以实现两个`dataset`中的拼接\n", + "\n", + "  通过`len`可以统计`dataset`中的实例数目;`dataset`的全部变量与函数可以通过`dir(dataset)`查询" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "25ce5488", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3 False\n", + "6 True\n", + "+------------------------------+------------------------------+--------+\n", + "| sentence | words | length |\n", + "+------------------------------+------------------------------+--------+\n", + "| This is an apple . | ['This', 'is', 'an', 'app... | 5 |\n", + "| I like apples . | ['I', 'like', 'apples', '... | 4 |\n", + "| Apples are good for our h... | ['Apples', 'are', 'good',... | 7 |\n", + "| This is an apple . | ['This', 'is', 'an', 'app... | 5 |\n", + "| I like apples . | ['I', 'like', 'apples', '... | 4 |\n", + "| Apples are good for our h... | ['Apples', 'are', 'good',... | 7 |\n", + "+------------------------------+------------------------------+--------+\n" + ] + } + ], + "source": [ + "print(len(dataset), dataset.has_field('length')) \n", + "if 'num' in dataset:\n", + " dataset.rename_field('num', 'length')\n", + "elif 'length' in dataset:\n", + " dataset.rename_field('length', 'num')\n", + "dataset.concat(dataset)\n", + "print(len(dataset), dataset.has_field('length')) \n", + "print(dataset) " + ] + }, + { + "cell_type": "markdown", + "id": "e30a6cd7", + "metadata": {}, + "source": [ + "## 2. vocabulary 的结构与使用\n", + "\n", + "### 2.1 vocabulary 的创建与修改\n", + "\n", + "在`fastNLP 1.0`中,使用`Vocabulary`模块表示词汇表,**vocabulary 的核心是从单词到序号的映射**\n", + "\n", + "  可以直接通过构造函数实例化,通过查找`word2idx`属性,可以找到`vocabulary`映射对应的字典实现\n", + "\n", + "  **默认补零 padding 用 \\ 表示**,**对应序号为0**;**未知单词 unknown 用 \\ 表示**,**对应序号1**\n", + "\n", + "  通过打印`vocabulary`可以看到词汇表中的单词列表,其中,`padding`和`unknown`不会显示" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3515e096", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Vocabulary([]...)\n", + "{'': 0, '': 1}\n", + " 0\n", + " 1\n" + ] + } + ], + "source": [ + "from fastNLP import Vocabulary\n", + "\n", + "vocab = Vocabulary()\n", + "print(vocab)\n", + "print(vocab.word2idx)\n", + "print(vocab.padding, vocab.padding_idx)\n", + "print(vocab.unknown, vocab.unknown_idx)" + ] + }, + { + "cell_type": "markdown", + "id": "640be126", + "metadata": {}, + "source": [ + "在`vocabulary`中,通过`add_word`方法或`add_word_lst`方法,可以单独或批量添加单词\n", + "\n", + "  通过`len`或`word_count`属性,可以显示`vocabulary`的单词量和每个单词添加的次数" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "88c7472a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5 Counter({'生活': 1, '就像': 1, '海洋': 1})\n", + "6 Counter({'生活': 1, '就像': 1, '海洋': 1, '只有': 1})\n", + "6 {'': 0, '': 1, '生活': 2, '就像': 3, '海洋': 4, '只有': 5}\n" + ] + } + ], + "source": [ + "vocab.add_word_lst(['生活', '就像', '海洋'])\n", + "print(len(vocab), vocab.word_count)\n", + "vocab.add_word('只有')\n", + "print(len(vocab), vocab.word_count)\n", + "print(len(vocab), vocab.word2idx)" + ] + }, + { + "cell_type": "markdown", + "id": "f9ec8b28", + "metadata": {}, + "source": [ + "  **通过 to_word 方法可以找到单词对应的序号**,**通过 to_index 方法可以找到序号对应的单词**\n", + "\n", + "    由于序号0和序号1已经被占用,所以**新加入的词的序号从2开始计数**,如`'生活'`对应2\n", + "\n", + "    通过`has_word`方法可以判断单词是否在词汇表中,没有的单词被判做``" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "3447acde", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 0\n", + " 1\n", + "生活 2\n", + "彼岸 1 False\n" + ] + } + ], + "source": [ + "print(vocab.to_word(0), vocab.to_index(''))\n", + "print(vocab.to_word(1), vocab.to_index(''))\n", + "print(vocab.to_word(2), vocab.to_index('生活'))\n", + "print('彼岸', vocab.to_index('彼岸'), vocab.has_word('彼岸'))" + ] + }, + { + "cell_type": "markdown", + "id": "b4e36850", + "metadata": {}, + "source": [ + "**vocabulary 允许反复添加相同单词**,**可以通过 word_count 方法看到相应单词被添加的次数**\n", + "\n", + "  但其中没有``和``,`vocabulary`的全部变量与函数可以通过`dir(vocabulary)`查询\n", + "\n", + "  注:**使用 add_word_lst 添加单词**,**单词对应序号不会动态调整**,**使用 dataset 添加单词的情况不同**" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "490b101c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "生活 2\n", + "彼岸 12 True\n", + "13 Counter({'人': 4, '生活': 2, '就像': 2, '海洋': 2, '只有': 2, '意志': 1, '坚强的': 1, '才': 1, '能': 1, '到达': 1, '彼岸': 1})\n", + "13 {'': 0, '': 1, '生活': 2, '就像': 3, '海洋': 4, '只有': 5, '人': 6, '意志': 7, '坚强的': 8, '才': 9, '能': 10, '到达': 11, '彼岸': 12}\n" + ] + } + ], + "source": [ + "vocab.add_word_lst(['生活', '就像', '海洋', '只有', '意志', '坚强的', '人', '人', '人', '人', '才', '能', '到达', '彼岸'])\n", + "print(vocab.to_word(2), vocab.to_index('生活'))\n", + "print('彼岸', vocab.to_index('彼岸'), vocab.has_word('彼岸'))\n", + "print(len(vocab), vocab.word_count)\n", + "print(len(vocab), vocab.word2idx)" + ] + }, + { + "cell_type": "markdown", + "id": "23e32a63", + "metadata": {}, + "source": [ + "### 2.2 vocabulary 与 OOV 问题\n", + "\n", + "在`vocabulary`模块初始化的时候,可以通过指定`unknown`和`padding`为`None`,限制其存在\n", + "\n", + "  此时添加单词直接从0开始标号,如果遇到未知单词会直接报错,即 out of vocabulary" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a99ff909", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'positive': 0, 'negative': 1}\n", + "ValueError: word `neutral` not in vocabulary\n" + ] + } + ], + "source": [ + "vocab = Vocabulary(unknown=None, padding=None)\n", + "\n", + "vocab.add_word_lst(['positive', 'negative'])\n", + "print(vocab.word2idx)\n", + "\n", + "try:\n", + " print(vocab.to_index('neutral'))\n", + "except ValueError:\n", + " print(\"ValueError: word `neutral` not in vocabulary\")" + ] + }, + { + "cell_type": "markdown", + "id": "618da6bd", + "metadata": {}, + "source": [ + "  相应的,如果只指定其中的`unknown`,则编号会后移一个,同时遇到未知单词全部当做``" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "432f74c1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'': 0, 'positive': 1, 'negative': 2}\n", + "0 \n" + ] + } + ], + "source": [ + "vocab = Vocabulary(unknown='', padding=None)\n", + "\n", + "vocab.add_word_lst(['positive', 'negative'])\n", + "print(vocab.word2idx)\n", + "\n", + "print(vocab.to_index('neutral'), vocab.to_word(vocab.to_index('neutral')))" + ] + }, + { + "cell_type": "markdown", + "id": "b6263f73", + "metadata": {}, + "source": [ + "## 3 dataset 和 vocabulary 的组合使用\n", + " \n", + "### 3.1 从 dataframe 中加载 dataset\n", + "\n", + "以下通过 [NLP-beginner](https://github.com/FudanNLP/nlp-beginner) 实践一中 [Rotten Tomatoes 影评数据集](https://www.kaggle.com/c/sentiment-analysis-on-movie-reviews) 的部分训练数据组成`test4dataset.tsv`文件\n", + "\n", + "  介绍如何使用`dataset`、`vocabulary`简单加载并处理数据集,首先使用`pandas`模块,读取原始数据的`dataframe`" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "3dbd985d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SentenceIdSentenceSentiment
01A series of escapades demonstrating the adage ...negative
12This quiet , introspective and entertaining in...positive
23Even fans of Ismail Merchant 's work , I suspe...negative
34A positively thrilling combination of ethnogra...neutral
45A comedy-drama of nearly epic proportions root...positive
56The Importance of Being Earnest , so thick wit...neutral
\n", + "
" + ], + "text/plain": [ + " SentenceId Sentence Sentiment\n", + "0 1 A series of escapades demonstrating the adage ... negative\n", + "1 2 This quiet , introspective and entertaining in... positive\n", + "2 3 Even fans of Ismail Merchant 's work , I suspe... negative\n", + "3 4 A positively thrilling combination of ethnogra... neutral\n", + "4 5 A comedy-drama of nearly epic proportions root... positive\n", + "5 6 The Importance of Being Earnest , so thick wit... neutral" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "df = pd.read_csv('./data/test4dataset.tsv', sep='\\t')\n", + "df" + ] + }, + { + "cell_type": "markdown", + "id": "919ab350", + "metadata": {}, + "source": [ + "接着,通过`dataset`中的`from_pandas`方法填充数据集,并使用`apply_more`方法对文本进行分词操作" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "4f634586", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Processing: 0%| | 0/6 [00:00': 0, '': 1, 'a': 2, 'of': 3, ',': 4, 'the': 5, '.': 6, 'is': 7, 'and': 8, 'good': 9, 'for': 10, 'which': 11, 'this': 12, \"'s\": 13, 'series': 14, 'escapades': 15, 'demonstrating': 16, 'adage': 17, 'that': 18, 'what': 19, 'goose': 20, 'also': 21, 'gander': 22, 'some': 23, 'occasionally': 24, 'amuses': 25, 'but': 26, 'none': 27, 'amounts': 28, 'to': 29, 'much': 30, 'story': 31, 'quiet': 32, 'introspective': 33, 'entertaining': 34, 'independent': 35, 'worth': 36, 'seeking': 37, 'even': 38, 'fans': 39, 'ismail': 40, 'merchant': 41, 'work': 42, 'i': 43, 'suspect': 44, 'would': 45, 'have': 46, 'hard': 47, 'time': 48, 'sitting': 49, 'through': 50, 'one': 51, 'positively': 52, 'thrilling': 53, 'combination': 54, 'ethnography': 55, 'all': 56, 'intrigue': 57, 'betrayal': 58, 'deceit': 59, 'murder': 60, 'shakespearean': 61, 'tragedy': 62, 'or': 63, 'juicy': 64, 'soap': 65, 'opera': 66, 'comedy-drama': 67, 'nearly': 68, 'epic': 69, 'proportions': 70, 'rooted': 71, 'in': 72, 'sincere': 73, 'performance': 74, 'by': 75, 'title': 76, 'character': 77, 'undergoing': 78, 'midlife': 79, 'crisis': 80, 'importance': 81, 'being': 82, 'earnest': 83, 'so': 84, 'thick': 85, 'with': 86, 'wit': 87, 'it': 88, 'plays': 89, 'like': 90, 'reading': 91, 'from': 92, 'bartlett': 93, 'familiar': 94, 'quotations': 95} \n", + "\n", + "Vocabulary(['a', 'series', 'of', 'escapades', 'demonstrating']...)\n" + ] + } + ], + "source": [ + "from fastNLP import Vocabulary\n", + "\n", + "vocab = Vocabulary()\n", + "vocab = vocab.from_dataset(dataset, field_name='Sentence')\n", + "print(vocab.word_count, '\\n')\n", + "print(vocab.word2idx, '\\n')\n", + "print(vocab)" + ] + }, + { + "cell_type": "markdown", + "id": "f0857ccb", + "metadata": {}, + "source": [ + "之后,**通过 vocabulary 的 index_dataset 方法**,**调整 dataset 中指定字段的元素**,**使用编号将之代替**\n", + "\n", + "  使用上述方法,可以将影评数据集中的单词序列转化为词编号序列,为接下来转化为词嵌入序列做准备" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "2f9a04b2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+------------+------------------------------+-----------+\n", + "| SentenceId | Sentence | Sentiment |\n", + "+------------+------------------------------+-----------+\n", + "| 1 | [2, 14, 3, 15, 16, 5, 17,... | negative |\n", + "| 2 | [12, 32, 4, 33, 8, 34, 35... | positive |\n", + "| 3 | [38, 39, 3, 40, 41, 13, 4... | negative |\n", + "| 4 | [2, 52, 53, 54, 3, 55, 8,... | neutral |\n", + "| 5 | [2, 67, 3, 68, 69, 70, 71... | positive |\n", + "| 6 | [5, 81, 3, 82, 83, 4, 84,... | neutral |\n", + "+------------+------------------------------+-----------+\n" + ] + } + ], + "source": [ + "vocab.index_dataset(dataset, field_name='Sentence')\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "6b26b707", + "metadata": {}, + "source": [ + "最后,使用相同方法,再将`dataset`中`Sentiment`字段中的`negative`、`neutral`、`positive`转化为数字编号" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "5f5eed18", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'negative': 0, 'positive': 1, 'neutral': 2}\n", + "+------------+------------------------------+-----------+\n", + "| SentenceId | Sentence | Sentiment |\n", + "+------------+------------------------------+-----------+\n", + "| 1 | [2, 14, 3, 15, 16, 5, 17,... | 0 |\n", + "| 2 | [12, 32, 4, 33, 8, 34, 35... | 1 |\n", + "| 3 | [38, 39, 3, 40, 41, 13, 4... | 0 |\n", + "| 4 | [2, 52, 53, 54, 3, 55, 8,... | 2 |\n", + "| 5 | [2, 67, 3, 68, 69, 70, 71... | 1 |\n", + "| 6 | [5, 81, 3, 82, 83, 4, 84,... | 2 |\n", + "+------------+------------------------------+-----------+\n" + ] + } + ], + "source": [ + "target_vocab = Vocabulary(padding=None, unknown=None)\n", + "\n", + "target_vocab.from_dataset(dataset, field_name='Sentiment')\n", + "print(target_vocab.word2idx)\n", + "target_vocab.index_dataset(dataset, field_name='Sentiment')\n", + "print(dataset)" + ] + }, + { + "cell_type": "markdown", + "id": "eed7ea64", + "metadata": {}, + "source": [ + "在最后的最后,通过以下的一张图,来总结本章关于`dataset`和`vocabulary`主要知识点的讲解,以及两者的联系\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35b4f0f7", + "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/docs/source/tutorials/fastnlp_tutorial_2.ipynb b/docs/source/tutorials/fastnlp_tutorial_2.ipynb new file mode 100644 index 00000000..546e471d --- /dev/null +++ b/docs/source/tutorials/fastnlp_tutorial_2.ipynb @@ -0,0 +1,884 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# T2. databundle 和 tokenizer 的基本使用\n", + "\n", + "  1   fastNLP 中 dataset 的延伸\n", + "\n", + "    1.1   databundle 的概念与使用\n", + "\n", + "  2   fastNLP 中的 tokenizer\n", + " \n", + "    2.1   PreTrainedTokenizer 的概念\n", + "\n", + "    2.2   BertTokenizer 的基本使用\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. fastNLP 中 dataset 的延伸\n", + "\n", + "### 1.1 databundle 的概念与使用\n", + "\n", + "在`fastNLP 1.0`中,在常用的数据加载模块`DataLoader`和数据集`DataSet`模块之间,还存在\n", + "\n", + "  一个中间模块,即 **数据包 DataBundle 模块**,可以从`fastNLP.io`路径中导入该模块\n", + "\n", + "在`fastNLP 1.0`中,**一个 databundle 数据包包含若干 dataset 数据集和 vocabulary 词汇表**\n", + "\n", + "  分别存储在`datasets`和`vocabs`两个变量中,所以了解`databundle`数据包之前\n", + "\n", + "需要首先**复习 dataset 数据集和 vocabulary 词汇表**,**下面的一串代码**,**你知道其大概含义吗?**\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\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/6 [00:00': 0, '': 1, 'negative': 2, 'positive': 3, 'neutral': 4}\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "from fastNLP import DataSet\n", + "from fastNLP import Vocabulary\n", + "from fastNLP.io import DataBundle\n", + "\n", + "datasets = DataSet.from_pandas(pd.read_csv('./data/test4dataset.tsv', sep='\\t'))\n", + "datasets.rename_field('Sentence', 'text')\n", + "datasets.rename_field('Sentiment', 'label')\n", + "datasets.apply_more(lambda ins:{'label': ins['label'].lower(), \n", + " 'text': ins['text'].lower().split()},\n", + " progress_bar='tqdm')\n", + "datasets.delete_field('SentenceId')\n", + "train_ds, test_ds = datasets.split(ratio=0.7)\n", + "datasets = {'train': train_ds, 'test': test_ds}\n", + "print(datasets['train'])\n", + "print(datasets['test'])\n", + "\n", + "vocabs = {}\n", + "vocabs['label'] = Vocabulary().from_dataset(datasets['train'].concat(datasets['test'], inplace=False), field_name='label')\n", + "vocabs['text'] = Vocabulary().from_dataset(datasets['train'].concat(datasets['test'], inplace=False), field_name='text')\n", + "print(vocabs['label'].word2idx)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "上述代码的含义是:从`test4dataset`的 6 条数据中,划分 4 条训练集(`int(6*0.7) = 4`),2 条测试集\n", + "\n", + "    修改相关字段名称,删除序号字段,同时将标签都设为小写,对文本进行分词\n", + "\n", + "  接着通过`concat`方法拼接测试集训练集,注意设置`inplace=False`,生成临时的新数据集\n", + "\n", + "  使用`from_dataset`方法从拼接的数据集中抽取词汇表,为将数据集中的单词替换为序号做准备\n", + "\n", + "由此就可以得到**数据集字典 datasets**(**对应训练集、测试集**)和**词汇表字典 vocabs**(**对应数据集各字段**)\n", + "\n", + "  然后就可以初始化`databundle`了,通过`print`可以观察其大致结构,效果如下" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In total 2 datasets:\n", + "\ttrain has 4 instances.\n", + "\ttest has 2 instances.\n", + "In total 2 vocabs:\n", + "\tlabel has 5 entries.\n", + "\ttext has 96 entries.\n", + "\n", + "['train', 'test']\n", + "['label', 'text']\n" + ] + } + ], + "source": [ + "data_bundle = DataBundle(datasets=datasets, vocabs=vocabs)\n", + "print(data_bundle)\n", + "print(data_bundle.get_dataset_names())\n", + "print(data_bundle.get_vocab_names())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "此外,也可以通过`data_bundle`的`num_dataset`和`num_vocab`返回数据表和词汇表个数\n", + "\n", + "  通过`data_bundle`的`iter_datasets`和`iter_vocabs`遍历数据表和词汇表" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In total 2 datasets:\n", + "\ttrain has 4 instances.\n", + "\ttest has 2 instances.\n", + "In total 2 datasets:\n", + "\tlabel has 5 entries.\n", + "\ttext has 96 entries.\n" + ] + } + ], + "source": [ + "print(\"In total %d datasets:\" % data_bundle.num_dataset)\n", + "for name, dataset in data_bundle.iter_datasets():\n", + " print(\"\\t%s has %d instances.\" % (name, len(dataset)))\n", + "print(\"In total %d datasets:\" % data_bundle.num_dataset)\n", + "for name, vocab in data_bundle.iter_vocabs():\n", + " print(\"\\t%s has %d entries.\" % (name, len(vocab)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在数据包`databundle`中,也有和数据集`dataset`类似的四个`apply`函数,即\n", + "\n", + "  `apply`函数、`apply_field`函数、`apply_field_more`函数和`apply_more`函数\n", + "\n", + "  负责对数据集进行预处理,如下所示是`apply_more`函数的示例,其他函数类似\n", + "\n", + "此外,通过`get_dataset`函数,可以通过数据表名`name`称找到对应数据表\n", + "\n", + "  通过`get_vocab`函数,可以通过词汇表名`field_name`称找到对应词汇表" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Processing: 0%| | 0/4 [00:00\n", + "在`fastNLP 1.0`中,**使用 PreTrainedTokenizer 模块来为数据集中的词语进行词向量的标注**\n", + "\n", + "  需要注意的是,`PreTrainedTokenizer`模块的下载和导入**需要确保环境安装了 transformers 模块**\n", + "\n", + "  这是因为 `fastNLP 1.0`中`PreTrainedTokenizer`模块的实现基于`Huggingface Transformers`库\n", + "\n", + "**Huggingface Transformers 是一个开源的**,**基于 transformer 模型结构提供的预训练语言库**\n", + "\n", + "  包含了多种经典的基于`transformer`的预训练模型,如`BERT`、`BART`、`RoBERTa`、`GPT2`、`CPT`\n", + "\n", + "  更多相关内容可以参考`Huggingface Transformers`的[相关论文](https://arxiv.org/pdf/1910.03771.pdf)、[官方文档](https://huggingface.co/transformers/)以及[的代码仓库](https://github.com/huggingface/transformers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 BertTokenizer 的基本使用\n", + "\n", + "在`fastNLP 1.0`中,以`PreTrainedTokenizer`为基类,泛化出多个子类,实现基于`BERT`等模型的标注\n", + "\n", + "  本节以`BertTokenizer`模块为例,展示`PreTrainedTokenizer`模块的使用方法与应用实例\n", + "\n", + "**BertTokenizer 的初始化包括 导入模块和导入数据 两步**,先通过从`fastNLP.transformers.torch`中\n", + "\n", + "  导入`BertTokenizer`模块,再**通过 from_pretrained 方法指定 tokenizer 参数类型下载**\n", + "\n", + "  其中,**'bert-base-uncased' 指定 tokenizer 使用的预训练 BERT 类型**:单词不区分大小写\n", + "\n", + "    **模块层数 L=12**,**隐藏层维度 H=768**,**自注意力头数 A=12**,**总参数量 110M**\n", + "\n", + "  另外,模型参数自动下载至 home 目录下的`~\\.cache\\huggingface\\transformers`文件夹中" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "from fastNLP.transformers.torch import BertTokenizer\n", + "\n", + "tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "通过变量`vocab_size`和`vocab_files_names`可以查看`BertTokenizer`的词汇表的大小和对应文件\n", + "\n", + "  通过变量`vocab`可以访问`BertTokenizer`预训练的词汇表(由于内容过大就不演示了" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30522 {'vocab_file': 'vocab.txt'}\n" + ] + } + ], + "source": [ + "print(tokenizer.vocab_size, tokenizer.vocab_files_names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "通过变量`all_special_tokens`或通过变量`special_tokens_map`可以**查看 BertTokenizer 内置的特殊词素**\n", + "\n", + "  包括**未知符 '[UNK]'**, **断句符 '[SEP]'**, **补零符 '[PAD]'**, **分类符 '[CLS]'**, **掩码 '[MASK]'**\n", + "\n", + "通过变量`all_special_ids`可以**查看 BertTokenizer 内置的特殊词素对应的词汇表编号**,相同功能\n", + "\n", + "  也可以直接通过查看`pad_token`,值为`'[UNK]'`,和`pad_token_id`,值为`0`,等变量来实现" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pad_token [PAD] 0\n", + "unk_token [UNK] 100\n", + "cls_token [CLS] 101\n", + "sep_token [SEP] 102\n", + "msk_token [MASK] 103\n", + "all_tokens ['[UNK]', '[SEP]', '[PAD]', '[CLS]', '[MASK]'] [100, 102, 0, 101, 103]\n", + "{'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}\n" + ] + } + ], + "source": [ + "print('pad_token', tokenizer.pad_token, tokenizer.pad_token_id) \n", + "print('unk_token', tokenizer.unk_token, tokenizer.unk_token_id) \n", + "print('cls_token', tokenizer.cls_token, tokenizer.cls_token_id) \n", + "print('sep_token', tokenizer.sep_token, tokenizer.sep_token_id)\n", + "print('msk_token', tokenizer.mask_token, tokenizer.mask_token_id)\n", + "print('all_tokens', tokenizer.all_special_tokens, tokenizer.all_special_ids)\n", + "print(tokenizer.special_tokens_map)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "此外,还可以添加其他特殊字符,例如起始符`[BOS]`、终止符`[EOS]`,添加后词汇表编号也会相应改变\n", + "\n", + "  *但是如何添加这两个之外的字符,并且如何将这两个的编号设置为 [UNK] 之外的编号???*" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bos_token [BOS] 100\n", + "eos_token [EOS] 100\n", + "all_tokens ['[BOS]', '[EOS]', '[UNK]', '[SEP]', '[PAD]', '[CLS]', '[MASK]'] [100, 100, 100, 102, 0, 101, 103]\n", + "{'bos_token': '[BOS]', 'eos_token': '[EOS]', 'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}\n" + ] + } + ], + "source": [ + "tokenizer.bos_token = '[BOS]'\n", + "tokenizer.eos_token = '[EOS]'\n", + "# tokenizer.bos_token_id = 104\n", + "# tokenizer.eos_token_id = 105\n", + "print('bos_token', tokenizer.bos_token, tokenizer.bos_token_id)\n", + "print('eos_token', tokenizer.eos_token, tokenizer.eos_token_id)\n", + "print('all_tokens', tokenizer.all_special_tokens, tokenizer.all_special_ids)\n", + "print(tokenizer.special_tokens_map)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在`BertTokenizer`中,**使用 tokenize 函数和 convert_tokens_to_string 函数可以实现文本和词素列表的互转**\n", + "\n", + "  此外,**使用 convert_tokens_to_ids 函数和 convert_ids_to_tokens 函数则可以实现词素和词素编号的互转**\n", + "\n", + "  上述四个函数的使用效果如下所示,此处可以明显看出,`tokenizer`分词和传统分词的不同效果,例如`'##cap'`" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204, 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681, 2572, 25581, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997, 1037, 2466, 1012]\n", + "['a', 'series', 'of', 'es', '##cap', '##ades', 'demonstrating', 'the', 'ada', '##ge', 'that', 'what', 'is', 'good', 'for', 'the', 'goose', 'is', 'also', 'good', 'for', 'the', 'gan', '##der', ',', 'some', 'of', 'which', 'occasionally', 'am', '##uses', 'but', 'none', 'of', 'which', 'amounts', 'to', 'much', 'of', 'a', 'story', '.']\n", + "a series of escapades demonstrating the adage that what is good for the goose is also good for the gander , some of which occasionally amuses but none of which amounts to much of a story .\n" + ] + } + ], + "source": [ + "text = \"a series of escapades demonstrating the adage that what is \" \\\n", + " \"good for the goose is also good for the gander , some of which \" \\\n", + " \"occasionally amuses but none of which amounts to much of a story .\" \n", + "tks = ['a', 'series', 'of', 'es', '##cap', '##ades', 'demonstrating', 'the', \n", + " 'ada', '##ge', 'that', 'what', 'is', 'good', 'for', 'the', 'goose', \n", + " 'is', 'also', 'good', 'for', 'the', 'gan', '##der', ',', 'some', 'of', \n", + " 'which', 'occasionally', 'am', '##uses', 'but', 'none', 'of', 'which', \n", + " 'amounts', 'to', 'much', 'of', 'a', 'story', '.']\n", + "ids = [ 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, \n", + " 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204,\n", + " 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681, 2572,\n", + " 25581, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997, 1037,\n", + " 2466, 1012]\n", + "\n", + "tokens = tokenizer.tokenize(text)\n", + "print(tokenizer.convert_tokens_to_ids(tokens))\n", + "\n", + "ids = tokenizer.convert_tokens_to_ids(tokens)\n", + "print(tokenizer.convert_ids_to_tokens(ids))\n", + "\n", + "print(tokenizer.convert_tokens_to_string(tokens))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在`BertTokenizer`中,还有另外两个函数可以实现分词标注,分别是 **encode 和 decode 函数**,**可以直接实现**\n", + "\n", + "  **文本字符串和词素编号列表的互转**,但是编码过程中会按照`BERT`的规则,**在句子首末加入 [CLS] 和 [SEP]**" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204, 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681, 2572, 25581, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997, 1037, 2466, 1012, 102]\n", + "[CLS] a series of escapades demonstrating the adage that what is good for the goose is also good for the gander, some of which occasionally amuses but none of which amounts to much of a story. [SEP]\n" + ] + } + ], + "source": [ + "enc = tokenizer.encode(text)\n", + "print(tokenizer.encode(text))\n", + "dec = tokenizer.decode(enc)\n", + "print(tokenizer.decode(enc))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在`encode`函数之上,还有`encode_plus`函数,这也是在数据预处理中,`BertTokenizer`模块最常用到的函数\n", + "\n", + "  **encode 函数的参数**,**encode_plus 函数都有**;**encode 函数词素编号列表**,**encode_plus 函数返回字典**\n", + "\n", + "在`encode_plus`函数的返回值中,字段`input_ids`表示词素编号,其余两个字段后文有详细解释\n", + "\n", + "  **字段 token_type_ids 详见 text_pairs 的示例**,**字段 attention_mask 详见 batch_text 的示例**\n", + "\n", + "在`encode_plus`函数的参数中,参数`add_special_tokens`表示是否按照`BERT`的规则,加入相关特殊字符\n", + "\n", + "  参数`max_length`表示句子截取最大长度(算特殊字符),在参数`truncation=True`时会自动截取\n", + "\n", + "  参数`return_attention_mask`约定返回的字典中是否包括`attention_mask`字段,以上案例如下" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'input_ids': [101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204, 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681, 2572, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}\n" + ] + } + ], + "source": [ + "text = \"a series of escapades demonstrating the adage that what is good for the goose is also good for \"\\\n", + " \"the gander , some of which occasionally amuses but none of which amounts to much of a story .\" \n", + "\n", + "encoded = tokenizer.encode_plus(text=text, add_special_tokens=True, max_length=32, \n", + " truncation=True, return_attention_mask=True)\n", + "print(encoded)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在`encode_plus`函数之上,还有`batch_encode_plus`函数(类似地,在`decode`之上,还有`batch_decode`\n", + "\n", + "  两者参数类似,**batch_encode_plus 函数针对批量文本 batch_text**,**或者批量句对 text_pairs**\n", + "\n", + "在针对批量文本`batch_text`的示例中,注意`batch_encode_plus`函数返回字典中的`attention_mask`字段\n", + "\n", + "  可以发现,**attention_mask 字段通过 01 标注出词素序列中该位置是否为补零**,可以用做自注意力的掩模" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'input_ids': [[101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, 2008, 102, 0, 0], [101, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204, 2005, 1996, 25957, 4063, 102], [101, 2070, 1997, 2029, 5681, 2572, 25581, 102, 0, 0, 0, 0, 0, 0, 0], [101, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997, 1037, 2466, 102, 0, 0, 0]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]]}\n" + ] + } + ], + "source": [ + "batch_text = [\"a series of escapades demonstrating the adage that\",\n", + " \"what is good for the goose is also good for the gander\",\n", + " \"some of which occasionally amuses\",\n", + " \"but none of which amounts to much of a story\" ]\n", + "\n", + "encoded = tokenizer.batch_encode_plus(batch_text_or_text_pairs=batch_text, padding=True,\n", + " add_special_tokens=True, max_length=16, truncation=True, \n", + " return_attention_mask=True)\n", + "print(encoded)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "而在针对批量句对`text_pairs`的示例中,注意`batch_encode_plus`函数返回字典中的`attention_mask`字段\n", + "\n", + "  可以发现,**token_type_ids 字段通过 01 标注出词素序列中该位置为句对中的第几句**,句对用 [SEP] 分割" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'input_ids': [[101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262, 3351, 2008, 102, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036, 2204, 2005, 1996, 25957, 4063, 102], [101, 2070, 1997, 2029, 5681, 2572, 25581, 102, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997, 1037, 2466, 102, 0, 0, 0, 0, 0, 0, 0, 0]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]}\n" + ] + } + ], + "source": [ + "text_pairs = [(\"a series of escapades demonstrating the adage that\",\n", + " \"what is good for the goose is also good for the gander\"),\n", + " (\"some of which occasionally amuses\",\n", + " \"but none of which amounts to much of a story\")]\n", + "\n", + "encoded = tokenizer.batch_encode_plus(batch_text_or_text_pairs=text_pairs, padding=True,\n", + " add_special_tokens=True, max_length=32, truncation=True, \n", + " return_attention_mask=True)\n", + "print(encoded)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "回到`encode_plus`上,在接下来的示例中,**使用内置的 functools.partial 模块构造 encode 函数**\n", + "\n", + "  接着**使用该函数对 databundle 进行数据预处理**,由于`tokenizer.encode_plus`返回的是一个字典\n", + "\n", + "  读入的是一个字段,所以此处使用`apply_field_more`方法,得到结果自动并入`databundle`中如下" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "functools.partial(, max_length=32, truncation=True, return_attention_mask=True)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Processing: 0%| | 0/4 [00:00\n", + "\n", + "在接下来的`tutorial 3.`中,将会介绍`fastNLP v1.0`中的`dataloader`模块,会涉及本章中\n", + "\n", + "  提到的`collator`模块,`fastNLP`的多框架适应以及完整的数据加载过程,敬请期待" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "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" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "metadata": { + "collapsed": false + }, + "source": [] + } + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/docs/source/tutorials/fastnlp_tutorial_3.ipynb b/docs/source/tutorials/fastnlp_tutorial_3.ipynb new file mode 100644 index 00000000..4100105a --- /dev/null +++ b/docs/source/tutorials/fastnlp_tutorial_3.ipynb @@ -0,0 +1,621 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "213d538c", + "metadata": {}, + "source": [ + "# T3. dataloader 的内部结构和基本使用\n", + "\n", + "  1   fastNLP 中的 dataloader\n", + " \n", + "    1.1   dataloader 的基本介绍\n", + "\n", + "    1.2   dataloader 的函数创建\n", + "\n", + "  2   fastNLP 中 dataloader 的延伸\n", + "\n", + "    2.1   collator 的概念与使用\n", + "\n", + "    2.2   结合 datasets 框架" + ] + }, + { + "cell_type": "markdown", + "id": "85857115", + "metadata": {}, + "source": [ + "## 1. fastNLP 中的 dataloader\n", + "\n", + "### 1.1 dataloader 的基本介绍\n", + "\n", + "在`fastNLP 1.0`的开发中,最关键的开发目标就是**实现 fastNLP 对当前主流机器学习框架**,例如\n", + "\n", + "  **当下流行的 pytorch**,以及**国产的 paddle 、jittor 和 oneflow 的兼容**,扩大受众的同时,也是助力国产\n", + "\n", + "本着分而治之的思想,我们可以将`fastNLP 1.0`对`pytorch`、`paddle`、`jittor`、`oneflow`框架的兼容,划分为\n", + "\n", + "    **对数据预处理**、**批量 batch 的划分与补齐**、**模型训练**、**模型评测**,**四个部分的兼容**\n", + "\n", + "  针对数据预处理,我们已经在`tutorial-1`中介绍了`dataset`和`vocabulary`的使用\n", + "\n", + "    而结合`tutorial-0`,我们可以发现**数据预处理环节本质上是框架无关的**\n", + "\n", + "    因为在不同框架下,读取的原始数据格式都差异不大,彼此也很容易转换\n", + "\n", + "只有涉及到张量、模型,不同框架才展现出其各自的特色:**pytorch 和 oneflow 中的 tensor 和 nn.Module**\n", + "\n", + "    **在 paddle 中称为 tensor 和 nn.Layer**,**在 jittor 中则称为 Var 和 Module**\n", + "\n", + "    因此,**模型训练、模型评测**,**是兼容的重难点**,我们将会在`tutorial-5`中详细介绍\n", + "\n", + "  针对批量`batch`的处理,作为`fastNLP 1.0`中框架无关部分想框架相关部分的过渡\n", + "\n", + "    就是`dataloader`模块的职责,这也是本篇教程`tutorial-3`讲解的重点\n", + "\n", + "**dataloader 模块的职责**,详细划分可以包含以下三部分,**采样划分、补零对齐、框架匹配**\n", + "\n", + "    第一,确定`batch`大小,确定采样方式,划分后通过迭代器即可得到`batch`序列\n", + "\n", + "    第二,对于序列处理,这也是`fastNLP`主要针对的,将同个`batch`内的数据对齐\n", + "\n", + "    第三,**batch 内数据格式要匹配框架**,**但 batch 结构需保持一致**,**参数匹配机制**\n", + "\n", + "  对此,`fastNLP 1.0`给出了 **TorchDataLoader 、 PaddleDataLoader 、 JittorDataLoader 和 OneflowDataLoader**\n", + "\n", + "    分别针对并匹配不同框架,但彼此之间参数名、属性、方法仍然类似,前两者大致如下表所示\n", + "\n", + "名称|参数|属性|功能|内容\n", + "----|----|----|----|----|\n", + " `dataset` | √ | √ | 指定`dataloader`的数据内容 | |\n", + " `batch_size` | √ | √ | 指定`dataloader`的`batch`大小 | 默认`16` |\n", + " `shuffle` | √ | √ | 指定`dataloader`的数据是否打乱 | 默认`False` |\n", + " `collate_fn` | √ | √ | 指定`dataloader`的`batch`打包方法 | 视框架而定 |\n", + " `sampler` | √ | √ | 指定`dataloader`的`__len__`和`__iter__`函数的实现 | 默认`None` |\n", + " `batch_sampler` | √ | √ | 指定`dataloader`的`__len__`和`__iter__`函数的实现 | 默认`None` |\n", + " `drop_last` | √ | √ | 指定`dataloader`划分`batch`时是否丢弃剩余的 | 默认`False` |\n", + " `cur_batch_indices` | | √ | 记录`dataloader`当前遍历批量序号 | |\n", + " `num_workers` | √ | √ | 指定`dataloader`开启子进程数量 | 默认`0` |\n", + " `worker_init_fn` | √ | √ | 指定`dataloader`子进程初始方法 | 默认`None` |\n", + " `generator` | √ | √ | 指定`dataloader`子进程随机种子 | 默认`None` |\n", + " `prefetch_factor` | | √ | 指定为每个`worker`装载的`sampler`数量 | 默认`2` |" + ] + }, + { + "cell_type": "markdown", + "id": "60a8a224", + "metadata": {}, + "source": [ + "  论及`dataloader`的函数,其中,`get_batch_indices`用来获取当前遍历到的`batch`序号,其他函数\n", + "\n", + "    包括`set_ignore`、`set_pad`和`databundle`类似,请参考`tutorial-2`,此处不做更多介绍\n", + "\n", + "    以下是`tutorial-2`中已经介绍过的数据预处理流程,接下来是对相关数据进行`dataloader`处理" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "aca72b49", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[38;5;2m[i 0604 15:44:29.773860 92 log.cc:351] Load log_sync: 1\u001b[m\n" + ] + }, + { + "data": { + "text/html": [ + "
\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/4 [00:00\n", + " ['input_ids', 'token_type_ids', 'attention_mask', 'target']\n", + "{'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),\n", + " 'input_ids': tensor([[ 101, 1037, 4038, 1011, 3689, 1997, 3053, 8680, 19173, 15685,\n", + " 1999, 1037, 18006, 2836, 2011, 1996, 2516, 2839, 14996, 3054,\n", + " 15509, 5325, 1012, 102, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0],\n", + " [ 101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262,\n", + " 3351, 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036,\n", + " 2204, 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681,\n", + " 2572, 25581, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997,\n", + " 1037, 2466, 1012, 102],\n", + " [ 101, 2130, 4599, 1997, 19214, 6432, 1005, 1055, 2147, 1010,\n", + " 1045, 8343, 1010, 2052, 2031, 1037, 2524, 2051, 3564, 2083,\n", + " 2023, 2028, 1012, 102, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0],\n", + " [ 101, 1037, 13567, 26162, 5257, 1997, 3802, 7295, 9888, 1998,\n", + " 2035, 1996, 20014, 27611, 1010, 14583, 1010, 11703, 20175, 1998,\n", + " 4028, 1997, 1037, 8101, 2319, 10576, 2030, 1037, 28900, 7815,\n", + " 3850, 1012, 102, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0]]),\n", + " 'target': tensor([0, 1, 1, 2]),\n", + " 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])}\n" + ] + } + ], + "source": [ + "from fastNLP import prepare_torch_dataloader\n", + "\n", + "train_dataset = data_bundle.get_dataset('train')\n", + "evaluate_dataset = data_bundle.get_dataset('dev')\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)\n", + "\n", + "print(type(train_dataloader))\n", + "\n", + "import pprint\n", + "\n", + "for batch in train_dataloader:\n", + " print(type(batch), type(batch['input_ids']), list(batch))\n", + " pprint.pprint(batch, width=1)" + ] + }, + { + "cell_type": "markdown", + "id": "9f457a6e", + "metadata": {}, + "source": [ + "之所以说`prepare_xx_dataloader`函数更方便,是因为其**导入对象不仅可也是 DataSet 类型**,**还可以**\n", + "\n", + "  **是 DataBundle 类型**,不过数据集名称需要是`'train'`、`'dev'`、`'test'`供`fastNLP`识别\n", + "\n", + "例如下方就是**直接通过 prepare_paddle_dataloader 函数生成基于 PaddleDataLoader 的字典**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7827557d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "from fastNLP import prepare_paddle_dataloader\n", + "\n", + "dl_bundle = prepare_paddle_dataloader(data_bundle, batch_size=16, shuffle=True)\n", + "\n", + "print(type(dl_bundle['train']))" + ] + }, + { + "cell_type": "markdown", + "id": "d898cf40", + "metadata": {}, + "source": [ + "  而在接下来`trainer`的初始化过程中,按如下方式使用即可,除了初始化时`driver='paddle'`外\n", + "\n", + "  这里也可以看出`trainer`模块中,**evaluate_dataloaders 的设计允许评测可以针对多个数据集**\n", + "\n", + "```python\n", + "trainer = Trainer(\n", + " model=model,\n", + " train_dataloader=dl_bundle['train'],\n", + " optimizers=optimizer,\n", + "\t...\n", + "\tdriver='paddle',\n", + "\tdevice='gpu',\n", + "\t...\n", + " evaluate_dataloaders={'dev': dl_bundle['dev'], 'test': dl_bundle['test']}, \n", + " metrics={'acc': Accuracy()},\n", + "\t...\n", + ")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "d74d0523", + "metadata": {}, + "source": [ + "## 2. fastNLP 中 dataloader 的延伸\n", + "\n", + "### 2.1 collator 的概念与使用\n", + "\n", + "在`fastNLP 1.0`中,在数据加载模块`dataloader`内部,如之前表格所列举的,还存在其他的一些模块\n", + "\n", + "  例如,**实现序列的补零对齐的核对器 collator 模块**;注:`collate vt. 整理(文件或书等);核对,校勘`\n", + "\n", + "在`fastNLP 1.0`中,虽然`dataloader`随框架不同,但`collator`模块却是统一的,主要属性、方法如下表所示\n", + "\n", + "名称|属性|方法|功能|内容\n", + " ----|----|----|----|----|\n", + " `backend` | √ | | 记录`collator`对应框架 | 字符串型,如`'torch'` |\n", + " `padders` | √ | | 记录各字段对应的`padder`,每个负责具体补零对齐  | 字典类型 |\n", + " `ignore_fields` | √ | | 记录`dataloader`采样`batch`时不予考虑的字段 | 集合类型 |\n", + " `input_fields` | √ | | 记录`collator`每个字段的补零值、数据类型等 | 字典类型 |\n", + " `set_backend` | | √ | 设置`collator`对应框架 | 字符串型,如`'torch'` |\n", + " `set_ignore` | | √ | 设置`dataloader`采样`batch`时不予考虑的字段 | 字符串型,表示`field_name`  |\n", + " `set_pad` | | √ | 设置`collator`每个字段的补零值、数据类型等 | |" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d0795b3e", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "train_dataloader.collate_fn\n", + "\n", + "print(type(train_dataloader.collate_fn))" + ] + }, + { + "cell_type": "markdown", + "id": "5f816ef5", + "metadata": {}, + "source": [ + "此外,还可以 **手动定义 dataloader 中的 collate_fn**,而不是使用`fastNLP 1.0`中自带的`collator`模块\n", + "\n", + "  该函数的定义可以大致如下,需要注意的是,**定义 collate_fn 之前需要了解 batch 作为字典的格式**\n", + "\n", + "  该函数通过`collate_fn`参数传入`dataloader`,**在 batch 分发**(**而不是 batch 划分**)**时调用**" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ff8e405e", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "\n", + "def collate_fn(batch):\n", + " input_ids, atten_mask, labels = [], [], []\n", + " max_length = [0] * 3\n", + " for each_item in batch:\n", + " input_ids.append(each_item['input_ids'])\n", + " max_length[0] = max(len(each_item['input_ids']), max_length[0])\n", + " atten_mask.append(each_item['token_type_ids'])\n", + " max_length[1] = max(len(each_item['token_type_ids']), max_length[1])\n", + " labels.append(each_item['attention_mask'])\n", + " max_length[2] = max(len(each_item['attention_mask']), max_length[2])\n", + "\n", + " for i in range(3):\n", + " each = (input_ids, atten_mask, labels)[i]\n", + " for item in each:\n", + " item.extend([0] * (max_length[i] - len(item)))\n", + " return {'input_ids': torch.cat([torch.tensor([item]) for item in input_ids], dim=0),\n", + " 'token_type_ids': torch.cat([torch.tensor([item]) for item in atten_mask], dim=0),\n", + " 'attention_mask': torch.cat([torch.tensor(item) for item in labels], dim=0)}" + ] + }, + { + "cell_type": "markdown", + "id": "487b75fb", + "metadata": {}, + "source": [ + "注意:使用自定义的`collate_fn`函数,`trainer`的`collate_fn`变量也会自动调整为`function`类型" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e916d1ac", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "{'attention_mask': tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n", + " 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0]),\n", + " 'input_ids': tensor([[ 101, 1037, 4038, 1011, 3689, 1997, 3053, 8680, 19173, 15685,\n", + " 1999, 1037, 18006, 2836, 2011, 1996, 2516, 2839, 14996, 3054,\n", + " 15509, 5325, 1012, 102, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0],\n", + " [ 101, 1037, 2186, 1997, 9686, 17695, 18673, 14313, 1996, 15262,\n", + " 3351, 2008, 2054, 2003, 2204, 2005, 1996, 13020, 2003, 2036,\n", + " 2204, 2005, 1996, 25957, 4063, 1010, 2070, 1997, 2029, 5681,\n", + " 2572, 25581, 2021, 3904, 1997, 2029, 8310, 2000, 2172, 1997,\n", + " 1037, 2466, 1012, 102],\n", + " [ 101, 2130, 4599, 1997, 19214, 6432, 1005, 1055, 2147, 1010,\n", + " 1045, 8343, 1010, 2052, 2031, 1037, 2524, 2051, 3564, 2083,\n", + " 2023, 2028, 1012, 102, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0],\n", + " [ 101, 1037, 13567, 26162, 5257, 1997, 3802, 7295, 9888, 1998,\n", + " 2035, 1996, 20014, 27611, 1010, 14583, 1010, 11703, 20175, 1998,\n", + " 4028, 1997, 1037, 8101, 2319, 10576, 2030, 1037, 28900, 7815,\n", + " 3850, 1012, 102, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0]]),\n", + " 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n", + " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])}\n" + ] + } + ], + "source": [ + "train_dataloader = prepare_torch_dataloader(train_dataset, collate_fn=collate_fn, shuffle=True)\n", + "evaluate_dataloader = prepare_torch_dataloader(evaluate_dataset, collate_fn=collate_fn, shuffle=True)\n", + "\n", + "print(type(train_dataloader))\n", + "print(type(train_dataloader.collate_fn))\n", + "\n", + "for batch in train_dataloader:\n", + " pprint.pprint(batch, width=1)" + ] + }, + { + "cell_type": "markdown", + "id": "0bd98365", + "metadata": {}, + "source": [ + "### 2.2 fastNLP 与 datasets 的结合\n", + "\n", + "从`tutorial-1`至`tutorial-3`,我们已经完成了对`fastNLP v1.0`数据读取、预处理、加载,整个流程的介绍\n", + "\n", + "  不过在实际使用中,我们往往也会采取更为简便的方法读取数据,例如使用`huggingface`的`datasets`模块\n", + "\n", + "**使用 datasets 模块中的 load_dataset 函数**,通过指定数据集两级的名称,示例中即是**GLUE 标准中的 SST-2 数据集**\n", + "\n", + "  即可以快速从网上下载好`SST-2`数据集读入,之后以`pandas.DataFrame`作为中介,再转化成`fastNLP.DataSet`\n", + "\n", + "  之后的步骤就和其他关于`dataset`、`databundle`、`vocabulary`、`dataloader`中介绍的相关使用相同了" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "91879c30", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "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": "639a0ad3c63944c6abef4e8ee1f7bf7c", + "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[16:20:10] INFO Running evaluator sanity check for 2 batches. trainer.py:596\n", + "\n" + ], + "text/plain": [ + "\u001b[2;36m[16:20:10]\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=908530;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=864197;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  self.msg_id = ip.kernel._parent_header['header']['msg_id']\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " self.msg_id = ip.kernel._parent_header['header']['msg_id']\n" + ] + }, + "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.525,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 84.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.525\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;36m84.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.54375,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 87.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.54375\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;36m87.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.55,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 88.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.55\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;36m88.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.625,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 100.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.625\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;36m100.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.65,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 104.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.65\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;36m104.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.69375,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 111.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.69375\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;36m111.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.675,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 108.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;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m108.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.66875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 107.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.66875\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;36m107.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.675,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 108.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;36m160.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m108.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.68125,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 109.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.68125\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;36m109.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": 8, + "id": "8bc4bfb2", + "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.712222, 'total#acc': 900.0, 'correct#acc': 641.0}"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "07538876",
+   "metadata": {},
+   "source": [
+    "  注:此处使用`gc`模块删除相关变量,释放内存,为接下来新的模型训练预留存储空间,下同"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "1b52eafd",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "383"
+      ]
+     },
+     "execution_count": 9,
+     "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": "d9443213",
+   "metadata": {},
+   "source": [
+    "## 2. fastNLP 中 models 模块的介绍\n",
+    "\n",
+    "### 2.1  示例一:models 实现 CNN 分类\n",
+    "\n",
+    "  本示例使用`fastNLP 1.0`中预定义模型`models`中的`CNNText`模型,实现`SST-2`文本二分类任务\n",
+    "\n",
+    "数据使用方面,此处沿用在上个示例中展示的`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",
+    "对应到代码上,**从 fastNLP.models.torch 路径下导入 CNNText**,初始化`CNNText`和`optimizer`实例\n",
+    "\n",
+    "  注意:初始化`CNNText`时,**二元组参数 embed 、分类数量 num_classes 是必须传入的**,其中\n",
+    "\n",
+    "    **embed 表示嵌入层的嵌入抽取矩阵大小**,因此第二个元素对应的是默认隐藏层维度 `100` 维"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "f6e76e2e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from fastNLP.models.torch import CNNText\n",
+    "\n",
+    "model = CNNText(embed=(len(vocab), 100), num_classes=2, dropout=0.1)\n",
+    "\n",
+    "from torch.optim import AdamW\n",
+    "\n",
+    "optimizers = AdamW(params=model.parameters(), lr=5e-4)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0cc5ca10",
+   "metadata": {},
+   "source": [
+    "  最后,使用`trainer`模块,集成`model`、`optimizer`、`dataloader`、`metric`训练"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "50a13ee5",
+   "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": 12,
+   "id": "28903a7d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
[16:21:57] INFO     Running evaluator sanity check for 2 batches.              trainer.py:596\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[16:21:57]\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=813103;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=271516;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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.654444,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 589.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.654444\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m589.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.767778,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 691.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.767778\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m691.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.797778,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 718.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.797778\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m718.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.803333,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 723.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.803333\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m723.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.807778,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 727.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.807778\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m727.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.812222,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 731.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.812222\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m731.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.804444,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 724.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.804444\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m724.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.811111,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 730.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.811111\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m730.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.811111,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 730.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.811111\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m730.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.806667,\n",
+       "  \"total#acc\": 900.0,\n",
+       "  \"correct#acc\": 726.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.806667\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m900.0\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m726.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()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "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.806667, 'total#acc': 900.0, 'correct#acc': 726.0}"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5b5c0446",
+   "metadata": {},
+   "source": [
+    "  注:此处使用`gc`模块删除相关变量,释放内存,为接下来新的模型训练预留存储空间,下同"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "e9e70f88",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "344"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "import gc\n",
+    "\n",
+    "del model\n",
+    "del trainer\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": 15,
+   "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": "593bc03ed5914953ab94268ff2f01710",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "  0%|          | 0/3 [00:00[16:23:41] INFO     Running evaluator sanity check for 2 batches.              trainer.py:596\n",
+       "\n"
+      ],
+      "text/plain": [
+       "\u001b[2;36m[16:23:41]\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=565652;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=224849;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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.169014,\n",
+       "  \"pre#F1\": 0.170732,\n",
+       "  \"rec#F1\": 0.167331\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.169014\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.170732\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.167331\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.361809,\n",
+       "  \"pre#F1\": 0.312139,\n",
+       "  \"rec#F1\": 0.430279\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.361809\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.312139\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.430279\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.525,\n",
+       "  \"pre#F1\": 0.475728,\n",
+       "  \"rec#F1\": 0.585657\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.525\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.475728\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.585657\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.627306,\n",
+       "  \"pre#F1\": 0.584192,\n",
+       "  \"rec#F1\": 0.677291\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.627306\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.584192\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.677291\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.710937,\n",
+       "  \"pre#F1\": 0.697318,\n",
+       "  \"rec#F1\": 0.7251\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.710937\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.697318\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.7251\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.739563,\n",
+       "  \"pre#F1\": 0.738095,\n",
+       "  \"rec#F1\": 0.741036\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.739563\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.738095\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.741036\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.748491,\n",
+       "  \"pre#F1\": 0.756098,\n",
+       "  \"rec#F1\": 0.741036\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.748491\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.756098\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.741036\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.716763,\n",
+       "  \"pre#F1\": 0.69403,\n",
+       "  \"rec#F1\": 0.741036\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.716763\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.69403\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.741036\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.768293,\n",
+       "  \"pre#F1\": 0.784232,\n",
+       "  \"rec#F1\": 0.752988\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.768293\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.784232\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.752988\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.757692,\n",
+       "  \"pre#F1\": 0.732342,\n",
+       "  \"rec#F1\": 0.784861\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#F1\"\u001b[0m: \u001b[1;36m0.757692\u001b[0m,\n", + " \u001b[1;34m\"pre#F1\"\u001b[0m: \u001b[1;36m0.732342\u001b[0m,\n", + " \u001b[1;34m\"rec#F1\"\u001b[0m: \u001b[1;36m0.784861\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": 21, + "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.766798, 'pre#F1': 0.741874, 'rec#F1': 0.793456}"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "96bae094",
+   "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/docs/source/tutorials/fastnlp_tutorial_5.ipynb b/docs/source/tutorials/fastnlp_tutorial_5.ipynb
new file mode 100644
index 00000000..ab759feb
--- /dev/null
+++ b/docs/source/tutorials/fastnlp_tutorial_5.ipynb
@@ -0,0 +1,1242 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "fdd7ff16",
+   "metadata": {},
+   "source": [
+    "# T5. trainer 和 evaluator 的深入介绍\n",
+    "\n",
+    "  1   fastNLP 中 driver 的补充介绍\n",
+    " \n",
+    "    1.1   trainer 和 driver 的构想 \n",
+    "\n",
+    "    1.2   device 与 多卡训练\n",
+    "\n",
+    "  2   fastNLP 中的更多 metric 类型\n",
+    "\n",
+    "    2.1   预定义的 metric 类型\n",
+    "\n",
+    "    2.2   自定义的 metric 类型\n",
+    "\n",
+    "  3   fastNLP 中 trainer 的补充介绍\n",
+    "\n",
+    "    3.1   trainer 的内部结构"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "08752c5a",
+   "metadata": {
+    "pycharm": {
+     "name": "#%% md\n"
+    }
+   },
+   "source": [
+    "## 1. fastNLP 中 driver 的补充介绍\n",
+    "\n",
+    "### 1.1  trainer 和 driver 的构想\n",
+    "\n",
+    "在`fastNLP 1.0`中,模型训练最关键的模块便是**训练模块 trainer 、评测模块 evaluator 、驱动模块 driver**,\n",
+    "\n",
+    "  在`tutorial 0`中,已经简单介绍过上述三个模块:**driver 用来控制训练评测中的 model 的最终运行**\n",
+    "\n",
+    "    **evaluator 封装评测的 metric**,**trainer 封装训练的 optimizer**,**也可以包括 evaluator**\n",
+    "\n",
+    "之所以做出上述的划分,其根本目的在于要**达成对于多个 python 学习框架**,**例如 pytorch 、 paddle 、 jittor 的兼容**\n",
+    "\n",
+    "  对于训练环节,其伪代码如下方左边紫色一栏所示,由于**不同框架对模型、损失、张量的定义各有不同**,所以将训练环节\n",
+    "\n",
+    "    划分为**框架无关的循环控制、批量分发部分**,**由 trainer 模块负责**实现,对应的伪代码如下方中间一栏所示\n",
+    "\n",
+    "    以及**随框架不同的模型调用、数值优化部分**,**由 driver 模块负责**实现,对应的伪代码如下方右边一栏所示\n",
+    "\n",
+    "|训练过程|框架无关 对应`Trainer`|框架相关 对应`Driver`\n",
+    "|----|----|----|\n",
+    "| try: | try: |  |\n",
+    "| for epoch in 1:n_eoochs: | for epoch in 1:n_eoochs: |  |\n",
+    "| for step in 1:total_steps: | for step in 1:total_steps: |  |\n",
+    "| batch = fetch_batch() | batch = fetch_batch() |  |\n",
+    "| loss = model.forward(batch)  |  | loss = model.forward(batch)  |\n",
+    "| loss.backward() |  | loss.backward() |\n",
+    "| model.clear_grad() |  | model.clear_grad() |\n",
+    "| model.update() |  | model.update() |\n",
+    "| if need_save: | if need_save: |  |\n",
+    "| model.save() |  | model.save() |\n",
+    "| except: | except: |  |\n",
+    "| process_exception() | process_exception() |  |"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3e55f07b",
+   "metadata": {},
+   "source": [
+    "  对于评测环节,其伪代码如下方左边紫色一栏所示,同样由于不同框架对模型、损失、张量的定义各有不同,所以将评测环节\n",
+    "\n",
+    "    划分为**框架无关的循环控制、分发汇总部分**,**由 evaluator 模块负责**实现,对应的伪代码如下方中间一栏所示\n",
+    "\n",
+    "    以及**随框架不同的模型调用、评测计算部分**,同样**由 driver 模块负责**实现,对应的伪代码如下方右边一栏所示\n",
+    "\n",
+    "|评测过程|框架无关 对应`Evaluator`|框架相关 对应`Driver`\n",
+    "|----|----|----|\n",
+    "| try: | try: |  |\n",
+    "| model.set_eval() | model.set_eval() |  |\n",
+    "| for step in 1:total_steps: | for step in 1:total_steps: |  |\n",
+    "| batch = fetch_batch() | batch = fetch_batch() |  |\n",
+    "| outputs = model.evaluate(batch)  |  | outputs = model.evaluate(batch)  |\n",
+    "| metric.compute(batch, outputs) |  | metric.compute(batch, outputs) |\n",
+    "| results = metric.get_metric() | results = metric.get_metric() |  |\n",
+    "| except: | except: |  |\n",
+    "| process_exception() | process_exception() |  |"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "94ba11c6",
+   "metadata": {
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   },
+   "source": [
+    "由此,从程序员的角度,`fastNLP v1.0` **通过一个 driver 让基于 pytorch 、 paddle 、 jittor 、 oneflow 框架的模型**\n",
+    "\n",
+    "    **都能在相同的 trainer 和 evaluator 上运行**,这也**是 fastNLP v1.0 相比于之前版本的一大亮点**\n",
+    "\n",
+    "  而从`driver`的角度,`fastNLP v1.0`通过定义一个`driver`基类,**将所有张量转化为 numpy.tensor**\n",
+    "\n",
+    "    并由此泛化出`torch_driver`、`paddle_driver`、`jittor_driver`三个子类,从而实现了\n",
+    "\n",
+    "    对`pytorch`、`paddle`、`jittor`的兼容,有关后两者的实践请参考接下来的`tutorial-6`"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ab1cea7d",
+   "metadata": {},
+   "source": [
+    "### 1.2  device 与 多卡训练\n",
+    "\n",
+    "**fastNLP v1.0 支持多卡训练**,实现方法则是**通过将 trainer 中的 device 设置为对应显卡的序号列表**\n",
+    "\n",
+    "  由单卡切换成多卡,无论是数据、模型还是评测都会面临一定的调整,`fastNLP v1.0`保证:\n",
+    "\n",
+    "    数据拆分时,不同卡之间相互协调,所有数据都可以被训练,且不会使用到相同的数据\n",
+    "\n",
+    "    模型训练时,模型之间需要交换梯度;评测计算时,每张卡先各自计算,再汇总结果\n",
+    "\n",
+    "  例如,在评测计算运行`get_metric`函数时,`fastNLP v1.0`将自动按照`self.right`和`self.total`\n",
+    "\n",
+    "    指定的 **aggregate_method 方法**,默认为`sum`,将每张卡上结果汇总起来,因此最终\n",
+    "\n",
+    "    在调用`get_metric`方法时,`Accuracy`类能够返回全部的统计结果,代码如下\n",
+    "    \n",
+    "```python\n",
+    "trainer = Trainer(\n",
+    "        model=model,                                # model 基于 pytorch 实现 \n",
+    "        train_dataloader=train_dataloader,\n",
+    "        optimizers=optimizer,\n",
+    "        ...\n",
+    "        driver='torch',                             # driver 使用 torch_driver \n",
+    "        device=[0, 1],                              # gpu 选择 cuda:0 + cuda:1\n",
+    "        ...\n",
+    "        evaluate_dataloaders=evaluate_dataloader,\n",
+    "        metrics={'acc': Accuracy()},\n",
+    "        ...\n",
+    "    )\n",
+    "\n",
+    "class Accuracy(Metric):\n",
+    "    def __init__(self):\n",
+    "        super().__init__()\n",
+    "        self.register_element(name='total', value=0, aggregate_method='sum')\n",
+    "        self.register_element(name='right', value=0, aggregate_method='sum')\n",
+    "```\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e2e0a210",
+   "metadata": {
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   },
+   "source": [
+    "注:`fastNLP v1.0`中要求`jupyter`不能多卡,仅能单卡,故在所有`tutorial`中均不作相关演示"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8d19220c",
+   "metadata": {},
+   "source": [
+    "## 2. fastNLP 中的更多 metric 类型\n",
+    "\n",
+    "### 2.1  预定义的 metric 类型\n",
+    "\n",
+    "在`fastNLP 1.0`中,除了前几篇`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": [
+    "  如`tutorial-0`中所述,所有的`metric`都包含`get_metric`和`update`函数,其中\n",
+    "\n",
+    "    **update 函数更新单个 batch 的统计量**,**get_metric 函数返回最终结果**,并打印显示\n",
+    "\n",
+    "\n",
+    "### 2.1.1  Accuracy 与 TransformersAccuracy\n",
+    "\n",
+    "`Accuracy`,正确率,预测正确的数据`right_num`在总数据`total_num`,中的占比(公式就不用列了\n",
+    "\n",
+    "  `get_metric`函数打印格式为 **{\"acc#xx\": float, 'total#xx': float, 'correct#xx': float}**\n",
+    "\n",
+    "  一般在初始化时不需要传参,`fastNLP`会根据`update`函数的传入参数确定对应后台框架`backend`\n",
+    "\n",
+    "  **update 函数的参数包括 pred 、 target 、 seq_len**,**后者用来标记批次中每笔数据的长度**\n",
+    "\n",
+    "`TransformersAccuracy`,继承自`Accuracy`,只是为了兼容`Transformers`框架中相关模型\n",
+    "\n",
+    "  在`update`函数中,将`Transformers`框架输出的`attention_mask`参数转化为`seq_len`参数\n",
+    "\n",
+    "\n",
+    "### 2.1.2  ClassifyFPreRecMetric 与 SpanFPreRecMetric\n",
+    "\n",
+    "`ClassifyFPreRecMetric`,分类评价,`SpanFPreRecMetric`,抽取评价,后者在`tutorial-4`中已出现\n",
+    "\n",
+    "  两者的相同之处在于:**第一**,**都包括召回率/查全率 ec**、**精确率/查准率 Pre**、**F1 值**这三个指标\n",
+    "\n",
+    "    `get_metric`函数打印格式为 **{\"f#xx\": float, 'pre#xx': float, 'rec#xx': float}**\n",
+    "\n",
+    "    三者的计算公式如下,其中`beta`默认为`1`,即`F1`值是召回率`Rec`和精确率`Pre`的调和平均数\n",
+    "\n",
+    "$$\\text{召回率}\\ Rec=\\dfrac{\\text{正确预测为正例的数量}}{\\text{所有本来是正例的数量}}\\qquad \\text{精确率}\\ Pre=\\dfrac{\\text{正确预测为正例的数量}}{\\text{所有预测为正例的数量}}$$\n",
+    "\n",
+    "$$F_{beta} = \\frac{(1 + {beta}^{2})*(Pre*Rec)}{({beta}^{2}*Pre + Rec)}$$\n",
+    "\n",
+    "  **第二**,可以通过参数`only_gross`为`False`,要求返回所有类别的`Rec-Pre-F1`,同时`F1`值又根据参数`f_type`又分为\n",
+    "\n",
+    "    **micro F1**(**直接统计所有类别的 Rec-Pre-F1**)、**macro F1**(**统计各类别的 Rec-Pre-F1 再算术平均**)\n",
+    "\n",
+    "  **第三**,两者在初始化时还可以**传入基于 fastNLP.Vocabulary 的 tag_vocab 参数记录数据集中的标签序号**\n",
+    "\n",
+    "    **与标签名称之间的映射**,通过字符串列表`ignore_labels`参数,指定若干标签不用于`Rec-Pre-F1`的计算\n",
+    "\n",
+    "两者的不同之处在于:`ClassifyFPreRecMetric`针对简单的分类问题,每个分类标签之间彼此独立,不构成标签对\n",
+    "\n",
+    "    **SpanFPreRecMetric 针对更复杂的抽取问题**,**规定标签 B-xx 和 I-xx 或 B-xx 和 E-xx 构成标签对**\n",
+    "\n",
+    "  在计算`Rec-Pre-F1`时,`ClassifyFPreRecMetric`只需要考虑标签本身是否正确这就足够了,但是\n",
+    "\n",
+    "    对于`SpanFPreRecMetric`,需要保证**标签符合规则且覆盖的区间与正确结果重合才算正确**\n",
+    "\n",
+    "    因此回到`tutorial-4`中`CoNLL-2003`的`NER`任务,如果评测方法选择`ClassifyFPreRecMetric`\n",
+    "\n",
+    "      或者`Accuracy`,会发现虽然评测结果显示很高,这是因为选择的评测方法要求太低\n",
+    "\n",
+    "    最后通过`CoNLL-2003`的词性标注`POS`任务简单演示下`ClassifyFPreRecMetric`相关的使用\n",
+    "\n",
+    "```python\n",
+    "from fastNLP import Vocabulary\n",
+    "from fastNLP import ClassifyFPreRecMetric\n",
+    "\n",
+    "tag_vocab = Vocabulary(padding=None, unknown=None)            # 记录序号与标签之间的映射\n",
+    "tag_vocab.add_word_lst(['\"', \"''\", '#', '$', '(', ')', ',', '.', ':', '``', \n",
+    "                        'CC', 'CD', 'DT', 'EX', 'FW', 'IN', 'JJ', 'JJR', 'JJS', 'LS', \n",
+    "                        'MD', 'NN', 'NNP', 'NNPS', 'NNS', 'NN|SYM', 'PDT', 'POS', 'PRP', 'PRP$', \n",
+    "                        'RB', 'RBR', 'RBS', 'RP', 'SYM', 'TO', 'UH', 'VB', 'VBD', 'VBG', \n",
+    "                        'VBN', 'VBP', 'VBZ', 'WDT', 'WP', 'WP+', 'WRB', ])  # CoNLL-2003 中的 pos_tags\n",
+    "ignore_labels = ['\"', \"''\", '#', '$', '(', ')', ',', '.', ':', '``', ]\n",
+    "\n",
+    "FPreRec = ClassifyFPreRecMetric(tag_vocab=tag_vocab,          \n",
+    "                                ignore_labels=ignore_labels,  # 表示评测/优化中不考虑上述标签的正误/损失\n",
+    "                                only_gross=True,              # 默认为 True 表示输出所有类别的综合统计结果\n",
+    "                                f_type='micro')               # 默认为 'micro' 表示统计所有类别的 Rec-Pre-F1\n",
+    "metrics = {'F1': FPreRec}\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "8a22f522",
+   "metadata": {},
+   "source": [
+    "### 2.2  自定义的 metric 类型\n",
+    "\n",
+    "如上文所述,`Metric`作为所有`metric`的基类,`Accuracy`等都是其子类,同样地,对于**自定义的 metric 类型**\n",
+    "\n",
+    "    也**需要继承自 Metric 类**,同时**内部自定义好 __init__ 、 update 和 get_metric 函数**\n",
+    "\n",
+    "  在`__init__`函数中,根据需求定义评测时需要用到的变量,此处沿用`Accuracy`中的`total_num`和`right_num`\n",
+    "\n",
+    "  在`update`函数中,根据需求定义评测变量的更新方式,需要注意的是如`tutorial-0`中所述,**update`的参数名**\n",
+    "\n",
+    "    **需要待评估模型在 evaluate_step 中的输出名称一致**,由此**和数据集中对应字段名称一致**,即**参数匹配**\n",
+    "\n",
+    "    在`fastNLP v1.0`中,`update`函数的默认输入参数:`pred`,对应预测值;`target`,对应真实值\n",
+    "\n",
+    "    此处仍然沿用,因为接下来会需要使用`fastNLP`函数的与定义模型,其输入参数格式即使如此\n",
+    "\n",
+    "  在`get_metric`函数中,根据需求定义评测指标最终的计算,此处直接计算准确率,该函数必须返回一个字典\n",
+    "\n",
+    "    其中,字串`'prefix'`表示该`metric`的名称,会对应显示到`trainer`的`progress bar`中\n",
+    "\n",
+    "根据上述要求,这里简单定义了一个名为`MyMetric`的评测模块,用于分类问题的评测,以此展开一个实例展示"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "08a872e9",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "\n", + "from fastNLP import Metric\n", + "\n", + "class MyMetric(Metric):\n", + "\n", + " def __init__(self):\n", + " Metric.__init__(self)\n", + " self.total_num = 0\n", + " self.right_num = 0\n", + "\n", + " def update(self, pred, target):\n", + " self.total_num += target.size(0)\n", + " self.right_num += target.eq(pred).sum().item()\n", + "\n", + " def get_metric(self, reset=True):\n", + " acc = self.right_num / self.total_num\n", + " if reset:\n", + " self.total_num = 0\n", + " self.right_num = 0\n", + " return {'prefix': acc}" + ] + }, + { + "cell_type": "markdown", + "id": "0155f447", + "metadata": {}, + "source": [ + "  数据使用方面,此处仍然使用`datasets`模块中的`load_dataset`函数,加载`SST-2`二分类数据集" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5ad81ac7", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "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": "ef923b90b19847f4916cccda5d33fc36", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00 0: # 如果设置了 num_eval_sanity_batch\n", + "\t\ton_sanity_check_begin(trainer)\n", + "\t\ton_sanity_check_end(trainer, sanity_check_res)\n", + "\ttry:\n", + "\t\ton_train_begin(trainer)\n", + "\t\twhile cur_epoch_idx < n_epochs:\n", + "\t\t\ton_train_epoch_begin(trainer)\n", + "\t\t\twhile batch_idx_in_epoch<=num_batches_per_epoch:\n", + "\t\t\t\ton_fetch_data_begin(trainer)\n", + "\t\t\t\tbatch = next(dataloader)\n", + "\t\t\t\ton_fetch_data_end(trainer)\n", + "\t\t\t\ton_train_batch_begin(trainer, batch, indices)\n", + "\t\t\t\ton_before_backward(trainer, outputs) # 其中 outputs 是经过 output_mapping 后的\n", + "\t\t\t\ton_after_backward(trainer)\n", + "\t\t\t\ton_before_zero_grad(trainer, optimizers) # 实际调用受到 accumulation_steps 影响\n", + "\t\t\t\ton_after_zero_grad(trainer, optimizers) # 实际调用受到 accumulation_steps 影响\n", + "\t\t\t\ton_before_optimizers_step(trainer, optimizers) # 实际调用受到 accumulation_steps 影响\n", + "\t\t\t\ton_after_optimizers_step(trainer, optimizers) # 实际调用受到 accumulation_steps 影响\n", + "\t\t\t\ton_train_batch_end(trainer)\n", + "\t\t\ton_train_epoch_end(trainer)\n", + "\texcept BaseException:\n", + "\t\tself.on_exception(trainer, exception)\n", + "\tfinally:\n", + "\t\ton_train_end(trainer)\n", + "``` -->" + ] + }, + { + "cell_type": "markdown", + "id": "1e21df35", + "metadata": {}, + "source": [ + "紧接着,初始化`trainer`实例,继续完成`SST-2`分类,其中`metrics`输入的键值对,字串`'suffix'`和之前定义的\n", + "\n", + "  字串`'prefix'`将拼接在一起显示到`progress bar`中,故完整的输出形式为`{'prefix#suffix': float}`" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "926a9c50", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import Trainer\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " driver='torch',\n", + " device=0, # 'cuda'\n", + " n_epochs=10,\n", + " optimizers=optimizers,\n", + " input_mapping=input_mapping,\n", + " train_dataloader=train_dataloader,\n", + " evaluate_dataloaders=evaluate_dataloader,\n", + " metrics={'suffix': MyMetric()}\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "b1b2e8b7", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "source": [ + "最后就是`run`函数的使用,关于其参数,这里也以表格形式列出,由此就解答了`num_eval_batch_per_dl=10`的含义\n", + "\n", + "|名称|功能|默认值|\n", + "|----|----|----|\n", + "| `num_train_batch_per_epoch` | 指定`trainer`训练时,每个循环计算批量数目 | 整数类型,默认`-1`,表示训练时,每个循环计算所有批量 |\n", + "| `num_eval_batch_per_dl` | 指定`trainer`评测时,每个循环计算批量数目 | 整数类型,默认`-1`,表示评测时,每个循环计算所有批量 |\n", + "| `num_eval_sanity_batch` | 指定`trainer`训练开始前,试探性评测批量数目 | 整数类型,默认`2`,表示训练开始前评估两个批量 |\n", + "| `resume_from` | 指定`trainer`恢复状态的路径,需要是文件夹 | 字符串型,默认`None`,使用可参考`CheckpointCallback` |\n", + "| `resume_training` | 指定`trainer`恢复状态的程度 | 布尔类型,默认`True`恢复所有状态,`False`仅恢复`model`和`optimizers`状态 |" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "43be274f", + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
[09:30:35] INFO     Running evaluator sanity check for 2 batches.              trainer.py:596\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[09:30:35]\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=954293;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=366534;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  self.msg_id = ip.kernel._parent_header['header']['msg_id']\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " self.msg_id = ip.kernel._parent_header['header']['msg_id']\n" + ] + }, + "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",
+       "  \"prefix#suffix\": 0.6875\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.6875\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",
+       "  \"prefix#suffix\": 0.8125\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.8125\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",
+       "  \"prefix#suffix\": 0.80625\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.80625\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",
+       "  \"prefix#suffix\": 0.825\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.825\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",
+       "  \"prefix#suffix\": 0.8125\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.8125\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",
+       "  \"prefix#suffix\": 0.80625\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.80625\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",
+       "  \"prefix#suffix\": 0.80625\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.80625\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",
+       "  \"prefix#suffix\": 0.8\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.8\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",
+       "  \"prefix#suffix\": 0.80625\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.80625\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",
+       "  \"prefix#suffix\": 0.80625\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"prefix#suffix\"\u001b[0m: \u001b[1;36m0.80625\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": null, + "id": "f1abfa0a", + "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" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "metadata": { + "collapsed": false + }, + "source": [] + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/tutorials/fastnlp_tutorial_6.ipynb b/docs/source/tutorials/fastnlp_tutorial_6.ipynb new file mode 100644 index 00000000..63f7481e --- /dev/null +++ b/docs/source/tutorials/fastnlp_tutorial_6.ipynb @@ -0,0 +1,1646 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdd7ff16", + "metadata": {}, + "source": [ + "# T6. fastNLP 与 paddle 或 jittor 的结合\n", + "\n", + "  1   fastNLP 结合 paddle 训练模型\n", + " \n", + "    1.1   关于 paddle 的简单介绍\n", + "\n", + "    1.2   使用 paddle 搭建并训练模型\n", + "\n", + "  2   fastNLP 结合 jittor 训练模型\n", + "\n", + "    2.1   关于 jittor 的简单介绍\n", + "\n", + "    2.2   使用 jittor 搭建并训练模型\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "08752c5a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "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": "6b13d42c39ba455eb370bf2caaa3a264", + "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 True\n" + ] + } + ], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "\n", + "from fastNLP import DataSet\n", + "\n", + "dataset = DataSet.from_pandas(sst2data['train'].to_pandas())[: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)\n", + "print(type(train_dataset), isinstance(train_dataset, DataSet))\n", + "\n", + "from fastNLP.io import DataBundle\n", + "\n", + "data_bundle = DataBundle(datasets={'train': train_dataset, 'dev': evaluate_dataset})" + ] + }, + { + "cell_type": "markdown", + "id": "57a3272f", + "metadata": {}, + "source": [ + "## 1. fastNLP 结合 paddle 训练模型\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e31b3198", + "metadata": {}, + "outputs": [], + "source": [ + "import paddle\n", + "import paddle.nn as nn\n", + "import paddle.nn.functional as F\n", + "\n", + "\n", + "class ClsByPaddle(nn.Layer):\n", + " def __init__(self, vocab_size, embedding_dim, output_dim, hidden_dim=64, dropout=0.5):\n", + " nn.Layer.__init__(self)\n", + " self.hidden_dim = hidden_dim\n", + "\n", + " self.embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embedding_dim)\n", + " \n", + " self.conv1 = nn.Sequential(nn.Conv1D(embedding_dim, 30, 1, padding=0), nn.ReLU())\n", + " self.conv2 = nn.Sequential(nn.Conv1D(embedding_dim, 40, 3, padding=1), nn.ReLU())\n", + " self.conv3 = nn.Sequential(nn.Conv1D(embedding_dim, 50, 5, padding=2), nn.ReLU())\n", + "\n", + " self.mlp = nn.Sequential(('dropout', nn.Dropout(p=dropout)),\n", + " ('linear_1', nn.Linear(120, hidden_dim)),\n", + " ('activate', nn.ReLU()),\n", + " ('linear_2', nn.Linear(hidden_dim, output_dim)))\n", + " \n", + " self.loss_fn = nn.MSELoss()\n", + "\n", + " def forward(self, words):\n", + " output = self.embedding(words).transpose([0, 2, 1])\n", + " conv1, conv2, conv3 = self.conv1(output), self.conv2(output), self.conv3(output)\n", + "\n", + " pool1 = F.max_pool1d(conv1, conv1.shape[-1]).squeeze(2)\n", + " pool2 = F.max_pool1d(conv2, conv2.shape[-1]).squeeze(2)\n", + " pool3 = F.max_pool1d(conv3, conv3.shape[-1]).squeeze(2)\n", + "\n", + " pool = paddle.concat([pool1, pool2, pool3], axis=1)\n", + " output = self.mlp(pool)\n", + " return output\n", + " \n", + " def train_step(self, words, target):\n", + " pred = self(words)\n", + " target = paddle.stack((1 - target, target), axis=1).cast(pred.dtype)\n", + " return {'loss': self.loss_fn(pred, target)}\n", + "\n", + " def evaluate_step(self, words, target):\n", + " pred = self(words)\n", + " pred = paddle.argmax(pred, axis=-1)\n", + " return {'pred': pred, 'target': target}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c63b030f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "W0604 21:02:25.453869 19014 gpu_context.cc:278] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 11.1, Runtime API Version: 10.2\n", + "W0604 21:02:26.061690 19014 gpu_context.cc:306] device: 0, cuDNN Version: 7.6.\n" + ] + }, + { + "data": { + "text/plain": [ + "ClsByPaddle(\n", + " (embedding): Embedding(8458, 100, sparse=False)\n", + " (conv1): Sequential(\n", + " (0): Conv1D(100, 30, kernel_size=[1], data_format=NCL)\n", + " (1): ReLU()\n", + " )\n", + " (conv2): Sequential(\n", + " (0): Conv1D(100, 40, kernel_size=[3], padding=1, data_format=NCL)\n", + " (1): ReLU()\n", + " )\n", + " (conv3): Sequential(\n", + " (0): Conv1D(100, 50, kernel_size=[5], padding=2, data_format=NCL)\n", + " (1): ReLU()\n", + " )\n", + " (mlp): Sequential(\n", + " (dropout): Dropout(p=0.5, axis=None, mode=upscale_in_train)\n", + " (linear_1): Linear(in_features=120, out_features=64, dtype=float32)\n", + " (activate): ReLU()\n", + " (linear_2): Linear(in_features=64, out_features=2, dtype=float32)\n", + " )\n", + " (loss_fn): MSELoss()\n", + ")" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model = ClsByPaddle(vocab_size=len(vocab), embedding_dim=100, output_dim=2)\n", + "\n", + "model" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2997c0aa", + "metadata": {}, + "outputs": [], + "source": [ + "from paddle.optimizer import AdamW\n", + "\n", + "optimizers = AdamW(parameters=model.parameters(), learning_rate=5e-4)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ead35fb8", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import prepare_paddle_dataloader\n", + "\n", + "train_dataloader = prepare_paddle_dataloader(train_dataset, batch_size=16, shuffle=True)\n", + "evaluate_dataloader = prepare_paddle_dataloader(evaluate_dataset, batch_size=16)\n", + "\n", + "# dl_bundle = prepare_paddle_dataloader(data_bundle, batch_size=16, shuffle=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "25e8da83", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import Trainer, Accuracy\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " driver='paddle',\n", + " device='gpu', # 'cpu', 'gpu', 'gpu:x'\n", + " n_epochs=10,\n", + " optimizers=optimizers,\n", + " train_dataloader=train_dataloader, # dl_bundle['train'],\n", + " evaluate_dataloaders=evaluate_dataloader, # dl_bundle['dev'], \n", + " metrics={'acc': Accuracy()}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d63c5d74", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[21:03:08] INFO     Running evaluator sanity check for 2 batches.              trainer.py:596\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[21:03:08]\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=894986;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=567751;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:111: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " if ip and hasattr(ip, 'kernel') and hasattr(ip.kernel, '_parent_header'):\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n",
+       "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n",
+       ".get_parent()\n",
+       "  self.msg_id = ip.kernel._parent_header['header']['msg_id']\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/ipywidgets/widgets/widget_\n", + "output.py:112: DeprecationWarning: Kernel._parent_header is deprecated in ipykernel 6. Use \n", + ".get_parent()\n", + " self.msg_id = ip.kernel._parent_header['header']['msg_id']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/paddle/tensor/creation.py:\n",
+       "125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To \n",
+       "silence this warning, use `object` by itself. Doing this will not modify any behavior and is \n",
+       "safe. \n",
+       "Deprecated in NumPy 1.20; for more details and guidance: \n",
+       "https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
+       "  if data.dtype == np.object:\n",
+       "
\n" + ], + "text/plain": [ + "/remote-home/xrliu/anaconda3/envs/demo/lib/python3.7/site-packages/paddle/tensor/creation.py:\n", + "125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To \n", + "silence this warning, use `object` by itself. Doing this will not modify any behavior and is \n", + "safe. \n", + "Deprecated in NumPy 1.20; for more details and guidance: \n", + "https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n", + " if data.dtype == np.object:\n" + ] + }, + "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.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: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.7875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 126.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.7875\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;36m126.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.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: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.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: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.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: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.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: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.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: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.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: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.7875,\n",
+       "  \"total#acc\": 160.0,\n",
+       "  \"correct#acc\": 126.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.7875\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;36m126.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.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"
+      ],
+      "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": "markdown", + "id": "cb9a0b3c", + "metadata": {}, + "source": [ + "## 2. fastNLP 结合 jittor 训练模型" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c600191d", + "metadata": {}, + "outputs": [], + "source": [ + "import jittor\n", + "import jittor.nn as nn\n", + "\n", + "from jittor import Module\n", + "\n", + "\n", + "class ClsByJittor(Module):\n", + " def __init__(self, vocab_size, embedding_dim, output_dim, hidden_dim=64, num_layers=2, dropout=0.5):\n", + " Module.__init__(self)\n", + " self.hidden_dim = hidden_dim\n", + "\n", + " self.embedding = nn.Embedding(num=vocab_size, dim=embedding_dim)\n", + " self.lstm = nn.LSTM(input_size=embedding_dim, hidden_size=hidden_dim, batch_first=True, # 默认 batch_first=False\n", + " num_layers=num_layers, bidirectional=True, dropout=dropout)\n", + " self.mlp = nn.Sequential([nn.Dropout(p=dropout),\n", + " nn.Linear(hidden_dim * 2, hidden_dim * 2),\n", + " nn.ReLU(),\n", + " nn.Linear(hidden_dim * 2, output_dim),\n", + " nn.Sigmoid(),])\n", + "\n", + " self.loss_fn = nn.MSELoss()\n", + "\n", + " def execute(self, words):\n", + " output = self.embedding(words)\n", + " output, (hidden, cell) = self.lstm(output)\n", + " output = self.mlp(jittor.concat((hidden[-1], hidden[-2]), dim=1))\n", + " return output\n", + " \n", + " def train_step(self, words, target):\n", + " pred = self(words)\n", + " target = jittor.stack((1 - target, target), dim=1)\n", + " return {'loss': self.loss_fn(pred, target)}\n", + "\n", + " def evaluate_step(self, words, target):\n", + " pred = self(words)\n", + " pred = jittor.argmax(pred, dim=-1)[0]\n", + " return {'pred': pred, 'target': target}" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a94ed8c4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ClsByJittor(\n", + " embedding: Embedding(8458, 100)\n", + " lstm: LSTM(100, 64, 2, bias=True, batch_first=True, dropout=0.5, bidirectional=True, proj_size=0)\n", + " mlp: Sequential(\n", + " 0: Dropout(0.5, is_train=False)\n", + " 1: Linear(128, 128, float32[128,], None)\n", + " 2: relu()\n", + " 3: Linear(128, 2, float32[2,], None)\n", + " 4: Sigmoid()\n", + " )\n", + " loss_fn: MSELoss(mean)\n", + ")" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model = ClsByJittor(vocab_size=len(vocab), embedding_dim=100, output_dim=2)\n", + "\n", + "model" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6d15ebc1", + "metadata": {}, + "outputs": [], + "source": [ + "from jittor.optim import AdamW\n", + "\n", + "optimizers = AdamW(params=model.parameters(), lr=5e-3)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "95d8d09e", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import prepare_jittor_dataloader\n", + "\n", + "train_dataloader = prepare_jittor_dataloader(train_dataset, batch_size=16, shuffle=True)\n", + "evaluate_dataloader = prepare_jittor_dataloader(evaluate_dataset, batch_size=16)\n", + "\n", + "# dl_bundle = prepare_jittor_dataloader(data_bundle, batch_size=16, shuffle=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "917eab81", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import Trainer, Accuracy\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " driver='jittor',\n", + " device='gpu', # 'cpu', 'gpu', 'cuda'\n", + " n_epochs=10,\n", + " optimizers=optimizers,\n", + " train_dataloader=train_dataloader, # dl_bundle['train'],\n", + " evaluate_dataloaders=evaluate_dataloader, # dl_bundle['dev'],\n", + " metrics={'acc': Accuracy()}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f7c4ac5a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[21:05:51] INFO     Running evaluator sanity check for 2 batches.              trainer.py:596\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[21:05:51]\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=69759;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=202322;file://../fastNLP/core/controllers/trainer.py#596\u001b\\\u001b[2m596\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"
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\n",
+      "Compiling Operators(5/6) used: 8.31s eta: 1.66s 6/6) used: 9.33s eta:    0s \n",
+      "\n",
+      "Compiling Operators(31/31) used: 7.31s eta:    0s \n"
+     ]
+    },
+    {
+     "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.61875,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 99\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.61875\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m99\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.7,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 112\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.7\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m112\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.725,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 116\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.725\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m116\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.74375,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 119\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.74375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m119\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.75625,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 121\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\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m121\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.75625,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 121\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\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m121\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.73125,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 117\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.73125\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m117\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.7625,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 122\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.7625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m122\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.74375,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 119\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.74375\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m119\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.7625,\n",
+       "  \"total#acc\": 160,\n",
+       "  \"correct#acc\": 122\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#acc\"\u001b[0m: \u001b[1;36m0.7625\u001b[0m,\n", + " \u001b[1;34m\"total#acc\"\u001b[0m: \u001b[1;36m160\u001b[0m,\n", + " \u001b[1;34m\"correct#acc\"\u001b[0m: \u001b[1;36m122\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": null, + "id": "3df5f425", + "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/docs/source/tutorials/fastnlp_tutorial_e1.ipynb b/docs/source/tutorials/fastnlp_tutorial_e1.ipynb new file mode 100644 index 00000000..af8e60a0 --- /dev/null +++ b/docs/source/tutorials/fastnlp_tutorial_e1.ipynb @@ -0,0 +1,1280 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "  从这篇开始,我们将开启 **fastNLP v1.0 tutorial 的 example 系列**,在接下来的\n", + "\n", + "  每篇`tutorial`里,我们将会介绍`fastNLP v1.0`在自然语言处理任务上的应用实例" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[, , ]\n" + ] + } + ], + "source": [ + "from pygments.plugin import find_plugin_lexers\n", + "print(list(find_plugin_lexers()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# E1. 使用 Bert + fine-tuning 完成 SST-2 分类\n", + "\n", + "  1   基础介绍:`GLUE`通用语言理解评估、`SST-2`文本情感二分类数据集 \n", + "\n", + "  2   准备工作:加载`tokenizer`、预处理`dataset`、`dataloader`使用\n", + "\n", + "  3   模型训练:加载`distilbert-base`、`fastNLP`参数匹配、`fine-tuning`" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.18.0\n" + ] + } + ], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "from torch.optim import AdamW\n", + "from torch.utils.data import DataLoader, Dataset\n", + "\n", + "import transformers\n", + "from transformers import AutoTokenizer\n", + "from transformers import AutoModelForSequenceClassification\n", + "\n", + "import sys\n", + "sys.path.append('..')\n", + "\n", + "import fastNLP\n", + "from fastNLP import Trainer\n", + "from fastNLP import Accuracy\n", + "\n", + "print(transformers.__version__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. 基础介绍:GLUE 通用语言理解评估、SST-2 文本情感二分类数据集\n", + "\n", + "  本示例使用`GLUE`评估基准中的`SST-2`数据集,通过`fine-tuning`方式\n", + "\n", + "    调整`distilbert-bert`分类模型,以下首先简单介绍下`GLUE`和`SST-2`\n", + "\n", + "**GLUE**,**全称 General Language Understanding Evaluation**,**通用语言理解评估**,\n", + "\n", + "  包含9个数据集,各语料的语言均为英语,涉及多个自然语言理解`NLU`任务,包括\n", + "\n", + "    **CoLA**,文本分类任务,预测单句语法正误分类;**SST-2**,文本分类任务,预测单句情感二分类\n", + "\n", + "    **MRPC**,句对分类任务,预测句对语义一致性;**STS-B**,相似度打分任务,预测句对语义相似度回归\n", + "\n", + "    **QQP**,句对分类任务,预测问题对语义一致性;**MNLI**,文本推理任务,预测句对蕴含/矛盾/中立预测\n", + "\n", + "    **QNLI / RTE / WNLI**,文本推理,预测是否蕴含二分类(其中,`QNLI`从`SQuAD`转化而来\n", + "\n", + "  诸如`BERT`、`T5`等经典模型都会在此基准上验证效果,更多参考[GLUE论文](https://arxiv.org/pdf/1804.07461v3.pdf)\n", + "\n", + "    此处,我们使用`SST-2`来训练`bert`,实现文本分类,其他任务描述见下图" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "GLUE_TASKS = ['cola', 'mnli', 'mrpc', 'qnli', 'qqp', 'rte', 'sst2', 'stsb', 'wnli']\n", + "\n", + "task = 'sst2'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "**SST**,**全称`Stanford Sentiment Treebank**,**斯坦福情感树库**,**单句情感分类**数据集\n", + "\n", + "  包含电影评论语句和对应的情感极性,1 对应`positive` 正面情感,0 对应`negative` 负面情感\n", + "\n", + "  数据集包括三部分:训练集 67350 条,验证集 873 条,测试集 1821 条,更多参考[下载链接](https://gluebenchmark.com/tasks)\n", + "\n", + "对应到代码上,此处使用`datasets`模块中的`load_dataset`函数,指定`SST-2`数据集,自动加载\n", + "\n", + "  首次下载后会保存至`~/.cache/huggingface/modules/datasets_modules/datasets/glue/`目录下" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "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": "c5915debacf9443986b5b3b34870b303", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00[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": [ + "
\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.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": [ + "
\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, + "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.884174, 'total#acc': 872.0, 'correct#acc': 771.0}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 附:`DistilBertForSequenceClassification`模块结构\n",
+    "\n",
+    "```\n",
+    "\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3.7.13 ('fnlp-paddle')",
+   "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"
+  },
+  "pycharm": {
+   "stem_cell": {
+    "cell_type": "raw",
+    "metadata": {
+     "collapsed": false
+    },
+    "source": []
+   }
+  },
+  "vscode": {
+   "interpreter": {
+    "hash": "31f2d9d3efc23c441973d7c4273acfea8b132b6a578f002629b6b44b8f65e720"
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/docs/source/tutorials/fastnlp_tutorial_e2.ipynb b/docs/source/tutorials/fastnlp_tutorial_e2.ipynb
new file mode 100644
index 00000000..588ee8c3
--- /dev/null
+++ b/docs/source/tutorials/fastnlp_tutorial_e2.ipynb
@@ -0,0 +1,1082 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# E2. 使用 Bert + prompt 完成 SST-2 分类\n",
+    "\n",
+    "  1   基础介绍:`prompt-based model`简介、与`fastNLP`的结合\n",
+    "\n",
+    "  2   准备工作:`P-Tuning v2`原理概述、`P-Tuning v2`模型搭建\n",
+    "\n",
+    "  3   模型训练:加载`tokenizer`、预处理`dataset`、模型训练与分析"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 1. 基础介绍:prompt-based model 简介、与 fastNLP 的结合\n",
+    "\n",
+    "  本示例使用`GLUE`评估基准中的`SST-2`数据集,通过`prompt-based tuning`方式\n",
+    "\n",
+    "    微调`bert-base-uncased`模型,实现文本情感的二分类,在此之前本示例\n",
+    "\n",
+    "    将首先简单介绍提示学习模型的研究,以及与`fastNLP v1.0`结合的优势\n",
+    "\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",
+    "\n",
+    "  其大致思路包括,对于文本分类任务,假定输入文本为`\" X . \"`,设计**输入模板 template**,**后来被称为 prompt**\n",
+    "\n",
+    "    将输入重构为`\" X . It is [MASK] . \"`,**诱导或刺激语言模型在 [MASK] 位置生成含有情感倾向的词汇**\n",
+    "\n",
+    "    接着将该词汇**输入分类器中**,**后来被称为 verbalizer**,从而得到该语句对应的情感倾向,实现文本分类\n",
+    "\n",
+    "  其主要贡献在于,通过构造`prompt`,诱导/刺激预训练模型生成期望适应下游任务特征,适合少样本学习的需求\n",
+    "\n",
+    "\n",
+    "\n",
+    "**prompt-based tuning**,**基于提示的微调**,将`prompt`应用于**参数高效微调**,**parameter-efficient tuning**\n",
+    "\n",
+    "  通过**设计模板调整模型输入**或者**调整模型内部状态**,**固定预训练模型**,**诱导/刺激模型**调整输出以适应\n",
+    "\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",
+    "  **案例一**:**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",
+    "  **案例二**:**P-Tuning v1**,详细内容参考[P-Tuning-v1论文](https://arxiv.org/pdf/2103.10385.pdf)\n",
+    "\n",
+    "    其主要贡献在于,**通过连续的、非人工构造的 prompt 调整模型输入**,取代原先基于单词设计的\n",
+    "\n",
+    "      但离散且不易于优化的`prompt`;同时也**证明了 GPT2 在语言理解任务上仍然是可以胜任的**\n",
+    "\n",
+    "    其主要研究对象,是`GPT2`,主要面向知识探测`knowledge probing`和自然语言理解`NLU`\n",
+    "\n",
+    "  **案例三**:**PromptTuning**,详细内容参考[PromptTuning论文](https://arxiv.org/pdf/2104.08691.pdf)\n",
+    "\n",
+    "    其主要贡献在于,通过连续的`prompt`调整模型输入,**证明了 prompt-based tuning 的效果**\n",
+    "\n",
+    "      **随模型参数量的增加而提升**,最终**在 10B 左右追上了全参数微调 fine-tuning 的效果**\n",
+    "\n",
+    "    其主要面向自然语言理解`NLU`,通过为每个任务定义不同的`prompt`,从而支持多任务语境\n",
+    "\n",
+    "通过上述介绍可以发现`prompt-based tuning`只是模型微调方式,独立于预训练模型基础`backbone`\n",
+    "\n",
+    "  目前,加载预训练模型的主流方法是使用**transformers 模块**,而实现微调的框架则\n",
+    "\n",
+    "    可以是`pytorch`、`paddle`、`jittor`等,而不同框架间又存在不兼容的问题\n",
+    "\n",
+    "  因此,**使用 fastNLP v1.0 实现 prompt-based tuning**,可以**很好地解决 paddle 等框架**\n",
+    "\n",
+    "    **和 transformers 模块之间的桥接**(`transformers`模块基于`pytorch`实现)\n",
+    "\n",
+    "本示例仍使用了`tutorial-E1`的`SST-2`数据集、`distilbert-base-uncased`模型(便于比较\n",
+    "\n",
+    "  使用`pytorch`框架,通过将连续的`prompt`与`model`拼接,解决`SST-2`二分类任务"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.18.0\n" + ] + } + ], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "from torch.optim import AdamW\n", + "from torch.utils.data import DataLoader, Dataset\n", + "\n", + "import transformers\n", + "from transformers import AutoTokenizer\n", + "from transformers import AutoModelForSequenceClassification\n", + "\n", + "import sys\n", + "sys.path.append('..')\n", + "\n", + "import fastNLP\n", + "from fastNLP import Trainer\n", + "from fastNLP.core.metrics import Accuracy\n", + "\n", + "print(transformers.__version__)\n", + "\n", + "task = 'sst2'\n", + "model_checkpoint = 'distilbert-base-uncased' # 'bert-base-uncased'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. 准备工作:P-Tuning v2 原理概述、P-Tuning v2 模型搭建\n", + "\n", + "  本示例使用`P-Tuning v2`作为`prompt-based tuning`与`fastNLP v1.0`结合的案例\n", + "\n", + "    以下首先简述`P-Tuning v2`的论文原理,并由此引出`fastNLP v1.0`的代码实践\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", + "\n", + "  其主要贡献在于,**在 PrefixTuning 等深度提示学习基础上**,**提升了其在分类标注等 NLU 任务的表现**\n", + "\n", + "    并使之在中等规模模型,主要是**参数量在 100M-1B 区间的模型上**,**获得与全参数微调相同的效果**\n", + "\n", + "  其结构如图所示,通过**在输入序列的分类符 [CLS] 之前**,**加入前缀序列**(**序号对应嵌入是待训练的连续值向量**\n", + "\n", + "    **刺激模型在新任务下**,从`[CLS]`对应位置,**输出符合微调任务的输出**,从而达到适应微调任务的目的\n", + "\n", + "\n", + "\n", + "本示例使用`bert-base-uncased`模型,作为`P-Tuning v2`的基础`backbone`,设置`requires_grad=False`\n", + "\n", + "    固定其参数不参与训练,**设置 pre_seq_len 长的 prefix_tokens 作为输入的提示前缀序列**\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": 2, + "metadata": {}, + "outputs": [], + "source": [ + "class SeqClsModel(nn.Module):\n", + " def __init__(self, model_checkpoint, num_labels, pre_seq_len):\n", + " nn.Module.__init__(self)\n", + " self.num_labels = num_labels\n", + " self.back_bone = AutoModelForSequenceClassification.from_pretrained(model_checkpoint, \n", + " num_labels=num_labels)\n", + " self.embeddings = self.back_bone.get_input_embeddings()\n", + "\n", + " for param in self.back_bone.parameters():\n", + " param.requires_grad = False\n", + " \n", + " self.pre_seq_len = pre_seq_len\n", + " self.prefix_tokens = torch.arange(self.pre_seq_len).long()\n", + " self.prefix_encoder = nn.Embedding(self.pre_seq_len, self.embeddings.embedding_dim)\n", + " \n", + " def get_prompt(self, batch_size):\n", + " prefix_tokens = self.prefix_tokens.unsqueeze(0).expand(batch_size, -1).to(self.back_bone.device)\n", + " prompts = self.prefix_encoder(prefix_tokens)\n", + " return prompts\n", + "\n", + " def forward(self, input_ids, attention_mask, labels=None):\n", + " \n", + " batch_size = input_ids.shape[0]\n", + " raw_embedding = self.embeddings(input_ids)\n", + " \n", + " prompts = self.get_prompt(batch_size=batch_size)\n", + " inputs_embeds = torch.cat((prompts, raw_embedding), dim=1)\n", + " prefix_attention_mask = torch.ones(batch_size, self.pre_seq_len).to(self.back_bone.device)\n", + " attention_mask = torch.cat((prefix_attention_mask, attention_mask), dim=1)\n", + "\n", + " outputs = self.back_bone(inputs_embeds=inputs_embeds, \n", + " attention_mask=attention_mask, labels=labels)\n", + " return outputs\n", + "\n", + " def train_step(self, input_ids, attention_mask, labels):\n", + " loss = self(input_ids, attention_mask, labels).loss\n", + " return {'loss': loss}\n", + "\n", + " def evaluate_step(self, input_ids, attention_mask, labels):\n", + " pred = self(input_ids, attention_mask, labels).logits\n", + " pred = torch.max(pred, dim=-1)[1]\n", + " return {'pred': pred, 'target': labels}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "接着,通过确定分类数量初始化模型实例,同时调用`torch.optim.AdamW`模块初始化优化器\n", + "\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": 3, + "metadata": {}, + "outputs": [ + { + "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.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" + ] + } + ], + "source": [ + "model = SeqClsModel(model_checkpoint=model_checkpoint, num_labels=2, pre_seq_len=20)\n", + "\n", + "optimizers = AdamW(params=model.parameters(), lr=1e-2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. 模型训练:加载 tokenizer、预处理 dataset、模型训练与分析\n", + "\n", + "  本示例沿用`tutorial-E1`中的数据集,即使用`GLUE`评估基准中的`SST-2`数据集\n", + "\n", + "    以`bert-base-uncased`模型作为基准,基于`P-Tuning v2`方式微调\n", + "\n", + "    数据集加载相关代码流程见下,内容和`tutorial-E1`中的内容基本一致\n", + "\n", + "首先,使用`datasets.load_dataset`加载数据集,使用`transformers.AutoTokenizer`\n", + "\n", + "  构建`tokenizer`实例,通过`dataset.map`使用`tokenizer`将文本替换为词素序号序列" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "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": "21cbd92c3397497d84dc10f017ec96f4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [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)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "可以发现,其效果远远逊色于`fine-tuning`,这是因为`P-Tuning v2`虽然能够适应参数量\n", + "\n", + "  在`100M-1B`区间的模型,但是,**distilbert-base 的参数量仅为 66M**,无法触及其下限\n", + "\n", + "另一方面,**fastNLP v1.0 不支持 jupyter 多卡**,所以无法在笔者的电脑/服务器上,完成\n", + "\n", + "  合适规模模型的学习,例如`110M`的`bert-base`模型,以及`340M`的`bert-large`模型" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "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.737385, 'total#acc': 872.0, 'correct#acc': 643.0}"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trainer.evaluator.run()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "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"
+  },
+  "pycharm": {
+   "stem_cell": {
+    "cell_type": "raw",
+    "metadata": {
+     "collapsed": false
+    },
+    "source": []
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/docs/source/tutorials/fastnlp_tutorial_paddle_e1.ipynb b/docs/source/tutorials/fastnlp_tutorial_paddle_e1.ipynb
new file mode 100644
index 00000000..a5883416
--- /dev/null
+++ b/docs/source/tutorials/fastnlp_tutorial_paddle_e1.ipynb
@@ -0,0 +1,1086 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# E3. 使用 paddlenlp 和 fastNLP 实现中文文本情感分析\n",
+    "\n",
+    "本篇教程属于 **fastNLP v1.0 tutorial 的 paddle examples 系列**。在本篇教程中,我们将为您展示如何使用 `paddlenlp` 自然语言处理库和 `fastNLP` 来完成比较简单的情感分析任务。\n",
+    "\n",
+    "1. 基础介绍:飞桨自然语言处理库 ``paddlenlp`` 和语义理解框架 ``ERNIE``\n",
+    "\n",
+    "2. 准备工作:使用 ``tokenizer`` 处理数据并构造 ``dataloader``\n",
+    "\n",
+    "3. 模型训练:加载 ``ERNIE`` 预训练模型,使用 ``fastNLP`` 进行训练"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 1. 基础介绍:飞桨自然语言处理库 paddlenlp 和语义理解框架 ERNIE\n",
+    "\n",
+    "#### 1.1 飞桨自然语言处理库 paddlenlp\n",
+    "\n",
+    "``paddlenlp`` 是由百度以飞桨 ``PaddlePaddle`` 为核心开发的自然语言处理库,集成了多个数据集和 NLP 模型,包括百度自研的语义理解框架 ``ERNIE`` 。在本篇教程中,我们会以 ``paddlenlp`` 为基础,使用模型 ``ERNIE`` 完成中文情感分析任务。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2.3.3\n"
+     ]
+    }
+   ],
+   "source": [
+    "import sys\n",
+    "sys.path.append(\"../\")\n",
+    "\n",
+    "import paddle\n",
+    "import paddlenlp\n",
+    "from paddlenlp.transformers import AutoTokenizer\n",
+    "from paddlenlp.transformers import AutoModelForSequenceClassification\n",
+    "\n",
+    "print(paddlenlp.__version__)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 1.2 语义理解框架 ERNIE\n",
+    "\n",
+    "``ERNIE(Enhanced Representation from kNowledge IntEgration)`` 是百度提出的基于知识增强的持续学习语义理解框架,至今已有 ``ERNIE 2.0``、``ERNIE 3.0``、``ERNIE-M``、``ERNIE-tiny`` 等多种预训练模型。``ERNIE 1.0`` 采用``Transformer Encoder`` 作为其语义表示的骨架,并改进了两种 ``mask`` 策略,分别为基于**短语**和**实体**(人名、组织等)的策略。在 ``ERNIE`` 中,由多个字组成的短语或者实体将作为一个统一单元,在训练的时候被统一地 ``mask`` 掉,这样可以潜在地学习到知识的依赖以及更长的语义依赖来让模型更具泛化性。\n",
+    "\n",
+    "\n",
+    "\n",
+    "\n",
+    "\n",
+    "``ERNIE 2.0`` 则提出了连续学习(``Continual Learning``)的概念,即首先用一个简单的任务来初始化模型,在更新时用前一个任务训练好的参数作为下一个任务模型初始化的参数。这样在训练新的任务时,模型便可以记住之前学习到的知识,使得模型在新任务上获得更好的表现。``ERNIE 2.0`` 分别构建了词法、语法、语义不同级别的预训练任务,并使用不同的 task id 来标示不同的任务,在共计16个中英文任务上都取得了SOTA效果。\n",
+    "\n",
+    "\n",
+    "\n",
+    "``ERNIE 3.0`` 将自回归和自编码网络融合在一起进行预训练,其中自编码网络采用 ``ERNIE 2.0`` 的多任务学习增量式构建预训练任务,持续进行语义理解学习。其中自编码网络增加了知识增强的预训练任务。自回归网络则基于 ``Tranformer-XL`` 结构,支持长文本语言模型建模,并在多个自然语言处理任务中取得了SOTA的效果。\n",
+    "\n",
+    "\n",
+    "\n",
+    "接下来,我们将展示如何在 ``fastNLP`` 中使用基于 ``paddle`` 的 ``ERNIE 1.0`` 框架进行中文情感分析。"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 2. 使用 tokenizer 处理数据并构造 dataloader\n",
+    "\n",
+    "#### 2.1 加载中文数据集 ChnSentiCorp\n",
+    "\n",
+    "``ChnSentiCorp`` 数据集是由中国科学院发布的中文句子级情感分析数据集,包含了从网络上获取的酒店、电影、书籍等多个领域的评论,每条评论都被划分为两个标签:消极(``0``)和积极(``1``),可以用于二分类的中文情感分析任务。通过 ``paddlenlp.datasets.load_dataset`` 函数,我们可以加载并查看 ``ChnSentiCorp`` 数据集的内容。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "训练集大小: 9600\n",
+      "{'text': '选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。酒店装修一般,但还算整洁。 泳池在大堂的屋顶,因此很小,不过女儿倒是喜欢。 包的早餐是西式的,还算丰富。 服务吗,一般', 'label': 1, 'qid': ''}\n",
+      "{'text': '15.4寸笔记本的键盘确实爽,基本跟台式机差不多了,蛮喜欢数字小键盘,输数字特方便,样子也很美观,做工也相当不错', 'label': 1, 'qid': ''}\n",
+      "{'text': '房间太小。其他的都一般。。。。。。。。。', 'label': 0, 'qid': ''}\n"
+     ]
+    }
+   ],
+   "source": [
+    "from paddlenlp.datasets import load_dataset\n",
+    "\n",
+    "train_dataset, val_dataset, test_dataset = load_dataset(\"chnsenticorp\", splits=[\"train\", \"dev\", \"test\"])\n",
+    "print(\"训练集大小:\", len(train_dataset))\n",
+    "for i in range(3):\n",
+    "    print(train_dataset[i])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 2.2 处理数据\n",
+    "\n",
+    "可以看到,原本的数据集仅包含中文的文本和标签,这样的数据是无法被模型识别的。同英文文本分类任务一样,我们需要使用 ``tokenizer`` 对文本进行分词并转换为数字形式的结果。我们可以加载已经预训练好的中文分词模型 ``ernie-1.0-base-zh``,将分词的过程写在函数 ``_process`` 中,然后调用数据集的 ``map`` 函数对每一条数据进行分词。其中:\n",
+    "- 参数 ``max_length`` 代表句子的最大长度;\n",
+    "- ``padding=\"max_length\"`` 表示将长度不足的结果 padding 至和最大长度相同;\n",
+    "- ``truncation=True`` 表示将长度过长的句子进行截断。\n",
+    "\n",
+    "至此,我们得到了每条数据长度均相同的数据集。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m[2022-06-22 21:31:04,168] [    INFO]\u001b[0m - We are using  to load 'ernie-1.0-base-zh'.\u001b[0m\n",
+      "\u001b[32m[2022-06-22 21:31:04,171] [    INFO]\u001b[0m - Already cached /remote-home/shxing/.paddlenlp/models/ernie-1.0-base-zh/vocab.txt\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'text': '选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。酒店装修一般,但还算整洁。 泳池在大堂的屋顶,因此很小,不过女儿倒是喜欢。 包的早餐是西式的,还算丰富。 服务吗,一般', 'label': 1, 'qid': '', 'input_ids': [1, 352, 790, 1252, 409, 283, 509, 5, 250, 196, 113, 10, 58, 518, 4, 9, 128, 70, 1495, 1855, 339, 293, 45, 302, 233, 554, 4, 544, 637, 1134, 774, 6, 494, 2068, 6, 278, 191, 6, 634, 99, 6, 2678, 144, 7, 149, 1573, 62, 12043, 661, 737, 371, 435, 7, 689, 4, 255, 201, 559, 407, 1308, 12043, 2275, 1110, 11, 19, 842, 5, 1207, 878, 4, 196, 198, 321, 96, 4, 16, 93, 291, 464, 1099, 10, 692, 811, 12043, 392, 5, 748, 1134, 10, 213, 220, 5, 4, 201, 559, 723, 595, 12043, 231, 112, 1114, 4, 7, 689, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}\n"
+     ]
+    }
+   ],
+   "source": [
+    "max_len = 128\n",
+    "model_checkpoint = \"ernie-1.0-base-zh\"\n",
+    "tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)\n",
+    "def _process(data):\n",
+    "    data.update(tokenizer(\n",
+    "        data[\"text\"],\n",
+    "        max_length=max_len,\n",
+    "        padding=\"max_length\",\n",
+    "        truncation=True,\n",
+    "        return_attention_mask=True,\n",
+    "    ))\n",
+    "    return data\n",
+    "\n",
+    "train_dataset.map(_process, num_workers=5)\n",
+    "val_dataset.map(_process, num_workers=5)\n",
+    "test_dataset.map(_process, num_workers=5)\n",
+    "\n",
+    "print(train_dataset[0])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "得到数据集之后,我们便可以将数据集包裹在 ``PaddleDataLoader`` 中,用于之后的训练。``fastNLP`` 提供的 ``PaddleDataLoader`` 拓展了 ``paddle.io.DataLoader`` 的功能,详情可以查看相关的文档。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from fastNLP.core import PaddleDataLoader\n",
+    "import paddle.nn as nn\n",
+    "\n",
+    "train_dataloader = PaddleDataLoader(train_dataset, batch_size=32, shuffle=True)\n",
+    "val_dataloader = PaddleDataLoader(val_dataset, batch_size=32, shuffle=False)\n",
+    "test_dataloader = PaddleDataLoader(test_dataset, batch_size=1, shuffle=False)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 3. 模型训练:加载 ERNIE 预训练模型,使用 fastNLP 进行训练\n",
+    "\n",
+    "#### 3.1 使用 ERNIE 预训练模型\n",
+    "\n",
+    "为了实现文本分类,我们首先需要定义文本分类的模型。``paddlenlp.transformers`` 提供了模型 ``AutoModelForSequenceClassification``,我们可以利用它来加载不同权重的文本分类模型。在 ``fastNLP`` 中,我们可以定义 ``train_step`` 和 ``evaluate_step`` 函数来实现训练和验证过程中的不同行为。\n",
+    "\n",
+    "- ``train_step`` 函数在获得返回值 ``logits`` (大小为 ``(batch_size, num_labels)``)后计算交叉熵损失 ``CrossEntropyLoss``,然后将 ``loss`` 放在字典中返回。``fastNLP`` 也支持返回 ``dataclass`` 类型的训练结果,但二者都需要包含名为 **loss** 的键或成员。\n",
+    "- ``evaluate_step`` 函数在获得返回值 ``logits`` 后,将 ``logits`` 和标签 ``label`` 放在字典中返回。\n",
+    "\n",
+    "这两个函数的参数均为数据集中字典**键**的子集,``fastNLP`` 会自动进行参数匹配然后输入到模型中。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m[2022-06-22 21:31:15,577] [    INFO]\u001b[0m - We are using  to load 'ernie-1.0-base-zh'.\u001b[0m\n",
+      "\u001b[32m[2022-06-22 21:31:15,580] [    INFO]\u001b[0m - Already cached /remote-home/shxing/.paddlenlp/models/ernie-1.0-base-zh/ernie_v1_chn_base.pdparams\u001b[0m\n"
+     ]
+    }
+   ],
+   "source": [
+    "import paddle.nn as nn\n",
+    "\n",
+    "class SeqClsModel(nn.Layer):\n",
+    "    def __init__(self, model_checkpoint, num_labels):\n",
+    "        super(SeqClsModel, self).__init__()\n",
+    "        self.model = AutoModelForSequenceClassification.from_pretrained(\n",
+    "            model_checkpoint,\n",
+    "            num_classes=num_labels,\n",
+    "        )\n",
+    "\n",
+    "    def forward(self, input_ids, attention_mask, token_type_ids):\n",
+    "        logits = self.model(input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)\n",
+    "        return logits\n",
+    "\n",
+    "    def train_step(self, input_ids, attention_mask, token_type_ids, label):\n",
+    "        logits = self(input_ids, attention_mask, token_type_ids)\n",
+    "        loss = nn.CrossEntropyLoss()(logits, label)\n",
+    "        return {\"loss\": loss}\n",
+    "\n",
+    "    def evaluate_step(self, input_ids, attention_mask, token_type_ids, label):\n",
+    "        logits = self(input_ids, attention_mask, token_type_ids)\n",
+    "        return {'pred': logits, 'target': label}\n",
+    "\n",
+    "model = SeqClsModel(model_checkpoint, num_labels=2)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 3.2 设置参数并使用 Trainer 开始训练\n",
+    "\n",
+    "现在我们可以着手使用 ``fastNLP.Trainer`` 进行训练了。\n",
+    "\n",
+    "首先,为了高效地训练 ``ERNIE`` 模型,我们最好为学习率指定一定的策略。``paddlenlp`` 提供的 ``LinearDecayWithWarmup`` 可以令学习率在一段时间内从 0 开始线性地增长(预热),然后再线性地衰减至 0 。在本篇教程中,我们将学习率设置为 ``5e-5``,预热时间为 ``0.1``,然后将得到的的 ``lr_scheduler`` 赋值给 ``AdamW`` 优化器。\n",
+    "\n",
+    "其次,我们还可以为 ``Trainer`` 指定多个 ``Callback`` 来在基础的训练过程之外进行额外的定制操作。在本篇教程中,我们使用的 ``Callback`` 有以下三种:\n",
+    "\n",
+    "- ``LRSchedCallback`` - 由于我们使用了 ``Scheduler``,因此需要将 ``lr_scheduler`` 传给该 ``Callback`` 以在训练中进行更新。\n",
+    "- ``LoadBestModelCallback`` - 该 ``Callback`` 会评估结果中的 ``'acc#accuracy'`` 值,保存训练中出现的正确率最高的模型,并在训练结束时加载到模型上,方便对模型进行测试和评估。\n",
+    "\n",
+    "在 ``Trainer`` 中,我们还可以设置 ``metrics`` 来衡量模型的表现。``Accuracy`` 能够根据传入的预测值和真实值计算出模型预测的正确率。还记得模型中 ``evaluate_step`` 函数的返回值吗?键 ``pred`` 和 ``target`` 分别为 ``Accuracy.update`` 的参数名,在验证过程中 ``fastNLP`` 会自动将键和参数名匹配从而计算出正确率,这也是我们规定模型需要返回字典类型数据的原因。\n",
+    "\n",
+    "``Accuracy`` 的返回值包含三个部分:``acc``、``total`` 和 ``correct``,分别代表 ``正确率``、 ``数据总数`` 和 ``预测正确的数目``,这让您能够直观地知晓训练中模型的变化,``LoadBestModelCallback`` 的参数 ``'acc#accuracy'`` 也正是代表了 ``accuracy`` 指标的 ``acc`` 结果。\n",
+    "\n",
+    "在设定好参数之后,调用 ``run`` 函数便可以进行训练和验证了。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
[21:31:16] INFO     Running evaluator sanity check for 2 batches.              trainer.py:631\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[21:31: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=4641;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=822054;file://../fastNLP/core/controllers/trainer.py#631\u001b\\\u001b[2m631\u001b[0m\u001b]8;;\u001b\\\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" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:0, Batch:60 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m60\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.895833,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1075.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.895833\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1075.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:0, Batch:120 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m120\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.8975,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1077.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.8975\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1077.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:0, Batch:180 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m180\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.911667,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1094.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.911667\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1094.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:0, Batch:240 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m240\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.9225,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1107.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.9225\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1107.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:0, Batch:300 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m300\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.9275,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1113.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.9275\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1113.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:1, Batch:60 -----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m60\u001b[0m -----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.930833,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1117.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.930833\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1117.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:1, Batch:120 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m120\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.935833,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1123.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.935833\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1123.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:1, Batch:180 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m180\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.935833,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1123.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.935833\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1123.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:1, Batch:240 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m240\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.9375,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1125.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.9375\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1125.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:1, Batch:300 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m1\u001b[0m, Batch:\u001b[1;36m300\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"acc#accuracy\": 0.941667,\n",
+       "  \"total#accuracy\": 1200.0,\n",
+       "  \"correct#accuracy\": 1130.0\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"acc#accuracy\"\u001b[0m: \u001b[1;36m0.941667\u001b[0m,\n", + " \u001b[1;34m\"total#accuracy\"\u001b[0m: \u001b[1;36m1200.0\u001b[0m,\n", + " \u001b[1;34m\"correct#accuracy\"\u001b[0m: \u001b[1;36m1130.0\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[21:34:28] INFO     Loading best model from fnlp-ernie/2022-0 load_best_model_callback.py:111\n",
+       "                    6-22-21_29_12_898095/best_so_far with                                    \n",
+       "                    acc#accuracy: 0.941667...                                                \n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[21:34:28]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Loading best model from fnlp-ernie/\u001b[1;36m2022\u001b[0m-\u001b[1;36m0\u001b[0m \u001b]8;id=340364;file://../fastNLP/core/callbacks/load_best_model_callback.py\u001b\\\u001b[2mload_best_model_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=763898;file://../fastNLP/core/callbacks/load_best_model_callback.py#111\u001b\\\u001b[2m111\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m \u001b[1;36m6\u001b[0m-\u001b[1;36m22\u001b[0m-21_29_12_898095/best_so_far with \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m acc#accuracy: \u001b[1;36m0.941667\u001b[0m\u001b[33m...\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[21:34:34] INFO     Deleting fnlp-ernie/2022-06-22-21_29_12_8 load_best_model_callback.py:131\n",
+       "                    98095/best_so_far...                                                     \n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[21:34:34]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Deleting fnlp-ernie/\u001b[1;36m2022\u001b[0m-\u001b[1;36m06\u001b[0m-\u001b[1;36m22\u001b[0m-21_29_12_8 \u001b]8;id=430330;file://../fastNLP/core/callbacks/load_best_model_callback.py\u001b\\\u001b[2mload_best_model_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=508566;file://../fastNLP/core/callbacks/load_best_model_callback.py#131\u001b\\\u001b[2m131\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m 98095/best_so_far\u001b[33m...\u001b[0m \u001b[2m \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": [ + "from fastNLP import LRSchedCallback, LoadBestModelCallback\n", + "from fastNLP import Trainer, Accuracy\n", + "from paddlenlp.transformers import LinearDecayWithWarmup\n", + "\n", + "n_epochs = 2\n", + "num_training_steps = len(train_dataloader) * n_epochs\n", + "lr_scheduler = LinearDecayWithWarmup(5e-5, num_training_steps, 0.1)\n", + "optimizer = paddle.optimizer.AdamW(\n", + " learning_rate=lr_scheduler,\n", + " parameters=model.parameters(),\n", + ")\n", + "callbacks = [\n", + " LRSchedCallback(lr_scheduler, step_on=\"batch\"),\n", + " LoadBestModelCallback(\"acc#accuracy\", larger_better=True, save_folder=\"fnlp-ernie\"),\n", + "]\n", + "trainer = Trainer(\n", + " model=model,\n", + " driver=\"paddle\",\n", + " optimizers=optimizer,\n", + " device=0,\n", + " n_epochs=n_epochs,\n", + " train_dataloader=train_dataloader,\n", + " evaluate_dataloaders=val_dataloader,\n", + " evaluate_every=60,\n", + " metrics={\"accuracy\": Accuracy()},\n", + " callbacks=callbacks,\n", + ")\n", + "trainer.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3.3 测试和评估\n", + "\n", + "现在我们已经得到了一个表现良好的 ``ERNIE`` 模型,接下来可以在测试集上测试模型的效果了。``fastNLP.Evaluator`` 提供了定制函数的功能。我们以 ``test_dataloader`` 初始化一个 ``Evaluator``,然后将写好的测试函数 ``test_batch_step_fn`` 传给参数 ``evaluate_batch_step_fn``,``Evaluate`` 在对每个 batch 进行评估时就会调用我们自定义的 ``test_batch_step_fn`` 函数而不是 ``evaluate_step`` 函数。在这里,我们仅测试 5 条数据并输出文本和对应的标签。" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
text: ['这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般']\n",
+       "
\n" + ], + "text/plain": [ + "text: ['这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
labels: 0\n",
+       "
\n" + ], + "text/plain": [ + "labels: 0\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
text: ['怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片!开始\n",
+       "还怀疑是不是赠送的个别现象,可是后来发现每张DVD后面都有!真不知道生产商怎么想的,我想看的是猫\n",
+       "和老鼠,不是米老鼠!如果厂家是想赠送的话,那就全套米老鼠和唐老鸭都赠送,只在每张DVD后面添加一\n",
+       "集算什么??简直是画蛇添足!!']\n",
+       "
\n" + ], + "text/plain": [ + "text: ['怀着十分激动的心情放映,可是看着看着发现,在放映完毕后,出现一集米老鼠的动画片!开始\n", + "还怀疑是不是赠送的个别现象,可是后来发现每张DVD后面都有!真不知道生产商怎么想的,我想看的是猫\n", + "和老鼠,不是米老鼠!如果厂家是想赠送的话,那就全套米老鼠和唐老鸭都赠送,只在每张DVD后面添加一\n", + "集算什么??简直是画蛇添足!!']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
labels: 0\n",
+       "
\n" + ], + "text/plain": [ + "labels: 0\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
text: ['还稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。其他要进一步验证。贴的几种膜气\n",
+       "泡较多,用不了多久就要更换了,屏幕膜稍好点,但比没有要强多了。建议配赠几张膜让用用户自己贴。'\n",
+       "]\n",
+       "
\n" + ], + "text/plain": [ + "text: ['还稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。其他要进一步验证。贴的几种膜气\n", + "泡较多,用不了多久就要更换了,屏幕膜稍好点,但比没有要强多了。建议配赠几张膜让用用户自己贴。'\n", + "]\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
labels: 0\n",
+       "
\n" + ], + "text/plain": [ + "labels: 0\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
text: ['交通方便;环境很好;服务态度很好 房间较小']\n",
+       "
\n" + ], + "text/plain": [ + "text: ['交通方便;环境很好;服务态度很好 房间较小']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
labels: 1\n",
+       "
\n" + ], + "text/plain": [ + "labels: 1\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
text: ['不错,作者的观点很颠覆目前中国父母的教育方式,其实古人们对于教育已经有了很系统的体系\n",
+       "了,可是现在的父母以及祖父母们更多的娇惯纵容孩子,放眼看去自私的孩子是大多数,父母觉得自己的\n",
+       "孩子在外面只要不吃亏就是好事,完全把古人几千年总结的教育古训抛在的九霄云外。所以推荐准妈妈们\n",
+       "可以在等待宝宝降临的时候,好好学习一下,怎么把孩子教育成一个有爱心、有责任心、宽容、大度的人\n",
+       "。']\n",
+       "
\n" + ], + "text/plain": [ + "text: ['不错,作者的观点很颠覆目前中国父母的教育方式,其实古人们对于教育已经有了很系统的体系\n", + "了,可是现在的父母以及祖父母们更多的娇惯纵容孩子,放眼看去自私的孩子是大多数,父母觉得自己的\n", + "孩子在外面只要不吃亏就是好事,完全把古人几千年总结的教育古训抛在的九霄云外。所以推荐准妈妈们\n", + "可以在等待宝宝降临的时候,好好学习一下,怎么把孩子教育成一个有爱心、有责任心、宽容、大度的人\n", + "。']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
labels: 1\n",
+       "
\n" + ], + "text/plain": [ + "labels: 1\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "{}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from fastNLP import Evaluator\n",
+    "def test_batch_step_fn(evaluator, batch):\n",
+    "    input_ids = batch[\"input_ids\"]\n",
+    "    attention_mask = batch[\"attention_mask\"]\n",
+    "    token_type_ids = batch[\"token_type_ids\"]\n",
+    "    logits = model(input_ids, attention_mask, token_type_ids)\n",
+    "    predict = logits.argmax().item()\n",
+    "    print(\"text:\", batch['text'])\n",
+    "    print(\"labels:\", predict)\n",
+    "\n",
+    "evaluator = Evaluator(\n",
+    "    model=model,\n",
+    "    dataloaders=test_dataloader,\n",
+    "    driver=\"paddle\",\n",
+    "    device=0,\n",
+    "    evaluate_batch_step_fn=test_batch_step_fn,\n",
+    ")\n",
+    "evaluator.run(5)    "
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3.7.13 ('fnlp-paddle')",
+   "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"
+  },
+  "orig_nbformat": 4,
+  "vscode": {
+   "interpreter": {
+    "hash": "31f2d9d3efc23c441973d7c4273acfea8b132b6a578f002629b6b44b8f65e720"
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/tutorials/fastnlp_tutorial_paddle_e2.ipynb b/docs/source/tutorials/fastnlp_tutorial_paddle_e2.ipynb
new file mode 100644
index 00000000..439d7f9f
--- /dev/null
+++ b/docs/source/tutorials/fastnlp_tutorial_paddle_e2.ipynb
@@ -0,0 +1,1510 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# E4. 使用 paddlenlp 和 fastNLP 训练中文阅读理解任务\n",
+    "\n",
+    "本篇教程属于 **fastNLP v1.0 tutorial 的 paddle examples 系列**。在本篇教程中,我们将为您展示如何在 `fastNLP` 中通过自定义 `Metric` 和 损失函数来完成进阶的问答任务。\n",
+    "\n",
+    "1. 基础介绍:自然语言处理中的阅读理解任务\n",
+    "\n",
+    "2. 准备工作:加载 `DuReader-robust` 数据集,并使用 `tokenizer` 处理数据\n",
+    "\n",
+    "3. 模型训练:自己定义评测用的 `Metric` 实现更加自由的任务评测"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 1. 基础介绍:自然语言处理中的阅读理解任务\n",
+    "\n",
+    "阅读理解任务,顾名思义,就是给出一段文字,然后让模型理解这段文字所含的语义。大部分机器阅读理解任务都采用问答式测评,即设计与文章内容相关的自然语言式问题,让模型理解问题并根据文章作答。与文本分类任务不同的是,在阅读理解任务中我们有时需要需要输入“一对”句子,分别代表问题和上下文;答案的格式也分为多种:\n",
+    "\n",
+    "- 多项选择:让模型从多个答案选项中选出正确答案\n",
+    "- 区间答案:答案为上下文的一段子句,需要模型给出答案的起始位置\n",
+    "- 自由回答:不做限制,让模型自行生成答案\n",
+    "- 完形填空:在原文中挖空部分关键词,让模型补全;这类答案往往不需要问题\n",
+    "\n",
+    "如果您对 `transformers` 有所了解的话,其中的 `ModelForQuestionAnswering` 系列模型就可以用于这项任务。阅读理解模型的泛用性是衡量该技术能否在实际应用中大规模落地的重要指标之一,随着当前技术的进步,许多模型虽然能够在一些测试集上取得较好的性能,但在实际应用中,这些模型仍然难以让人满意。在本篇教程中,我们将会为您展示如何训练一个问答模型。\n",
+    "\n",
+    "在这一领域,`SQuAD` 数据集是一个影响深远的数据集。它的全称是斯坦福问答数据集(Stanford Question Answering Dataset),每条数据包含 `(问题,上下文,答案)` 三部分,规模大(约十万条,2.0又新增了五万条),在提出之后很快成为训练问答任务的经典数据集之一。`SQuAD` 数据集有两个指标来衡量模型的表现:`EM`(Exact Match,精确匹配)和 `F1`(模糊匹配)。前者反应了模型给出的答案中有多少和正确答案完全一致,后者则反应了模型给出的答案中与正确答案重叠的部分,均为越高越好。"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 2. 准备工作:加载 DuReader-robust 数据集,并使用 tokenizer 处理数据"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/remote-home/shxing/anaconda3/envs/fnlp-paddle/lib/python3.7/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
+      "  from .autonotebook import tqdm as notebook_tqdm\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2.3.3\n"
+     ]
+    }
+   ],
+   "source": [
+    "import sys\n",
+    "sys.path.append(\"../\")\n",
+    "import paddle\n",
+    "import paddlenlp\n",
+    "\n",
+    "print(paddlenlp.__version__)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "在数据集方面,我们选用 `DuReader-robust` 中文数据集作为训练数据。它是一种抽取式问答数据集,采用 `SQuAD` 数据格式,能够评估真实应用场景下模型的泛用性。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "Reusing dataset dureader_robust (/remote-home/shxing/.cache/huggingface/datasets/dureader_robust/plain_text/1.0.0/d462ecadc8c010cee20f57632f1413f272867cd802a91a602df48c7d34eb0c27)\n",
+      "Reusing dataset dureader_robust (/remote-home/shxing/.cache/huggingface/datasets/dureader_robust/plain_text/1.0.0/d462ecadc8c010cee20f57632f1413f272867cd802a91a602df48c7d34eb0c27)\n",
+      "\u001b[32m[2022-06-27 19:22:46,998] [    INFO]\u001b[0m - Already cached /remote-home/shxing/.paddlenlp/models/ernie-1.0-base-zh/vocab.txt\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'id': '0a25cb4bc1ab6f474c699884e04601e4', 'title': '', 'context': '第35集雪见缓缓张开眼睛,景天又惊又喜之际,长卿和紫萱的仙船驶至,见众人无恙,也十分高兴。众人登船,用尽合力把自身的真气和水分输给她。雪见终于醒过来了,但却一脸木然,全无反应。众人向常胤求助,却发现人世界竟没有雪见的身世纪录。长卿询问清微的身世,清微语带双关说一切上了天界便有答案。长卿驾驶仙船,众人决定立马动身,往天界而去。众人来到一荒山,长卿指出,魔界和天界相连。由魔界进入通过神魔之井,便可登天。众人至魔界入口,仿若一黑色的蝙蝠洞,但始终无法进入。后来花楹发现只要有翅膀便能飞入。于是景天等人打下许多乌鸦,模仿重楼的翅膀,制作数对翅膀状巨物。刚佩戴在身,便被吸入洞口。众人摔落在地,抬头发现魔界守卫。景天和众魔套交情,自称和魔尊重楼相熟,众魔不理,打了起来。', 'question': '仙剑奇侠传3第几集上天界', 'answers': {'text': ['第35集'], 'answer_start': [0]}}\n",
+      "{'id': '7de192d6adf7d60ba73ba25cf590cc1e', 'title': '', 'context': '选择燃气热水器时,一定要关注这几个问题:1、出水稳定性要好,不能出现忽热忽冷的现象2、快速到达设定的需求水温3、操作要智能、方便4、安全性要好,要装有安全报警装置 市场上燃气热水器品牌众多,购买时还需多加对比和仔细鉴别。方太今年主打的磁化恒温热水器在使用体验方面做了全面升级:9秒速热,可快速进入洗浴模式;水温持久稳定,不会出现忽热忽冷的现象,并通过水量伺服技术将出水温度精确控制在±0.5℃,可满足家里宝贝敏感肌肤洗护需求;配备CO和CH4双气体报警装置更安全(市场上一般多为CO单气体报警)。另外,这款热水器还有智能WIFI互联功能,只需下载个手机APP即可用手机远程操作热水器,实现精准调节水温,满足家人多样化的洗浴需求。当然方太的磁化恒温系列主要的是增加磁化功能,可以有效吸附水中的铁锈、铁屑等微小杂质,防止细菌滋生,使沐浴水质更洁净,长期使用磁化水沐浴更利于身体健康。', 'question': '燃气热水器哪个牌子好', 'answers': {'text': ['方太'], 'answer_start': [110]}}\n",
+      "{'id': 'b9e74d4b9228399b03701d1fe6d52940', 'title': '', 'context': '迈克尔.乔丹在NBA打了15个赛季。他在84年进入nba,期间在1993年10月6日第一次退役改打棒球,95年3月18日重新回归,在99年1月13日第二次退役,后于2001年10月31日复出,在03年最终退役。迈克尔·乔丹(Michael Jordan),1963年2月17日生于纽约布鲁克林,美国著名篮球运动员,司职得分后卫,历史上最伟大的篮球运动员。1984年的NBA选秀大会,乔丹在首轮第3顺位被芝加哥公牛队选中。 1986-87赛季,乔丹场均得到37.1分,首次获得分王称号。1990-91赛季,乔丹连夺常规赛MVP和总决赛MVP称号,率领芝加哥公牛首次夺得NBA总冠军。 1997-98赛季,乔丹获得个人职业生涯第10个得分王,并率领公牛队第六次夺得总冠军。2009年9月11日,乔丹正式入选NBA名人堂。', 'question': '乔丹打了多少个赛季', 'answers': {'text': ['15个'], 'answer_start': [12]}}\n",
+      "训练集大小: 14520\n",
+      "验证集大小: 1417\n"
+     ]
+    }
+   ],
+   "source": [
+    "from paddlenlp.datasets import load_dataset\n",
+    "train_dataset = load_dataset(\"PaddlePaddle/dureader_robust\", splits=\"train\")\n",
+    "val_dataset = load_dataset(\"PaddlePaddle/dureader_robust\", splits=\"validation\")\n",
+    "for i in range(3):\n",
+    "    print(train_dataset[i])\n",
+    "print(\"训练集大小:\", len(train_dataset))\n",
+    "print(\"验证集大小:\", len(val_dataset))\n",
+    "\n",
+    "MODEL_NAME = \"ernie-1.0-base-zh\"\n",
+    "from paddlenlp.transformers import ErnieTokenizer\n",
+    "tokenizer =ErnieTokenizer.from_pretrained(MODEL_NAME)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 2.1 处理训练集\n",
+    "\n",
+    "对于阅读理解任务,数据处理的方式较为麻烦。接下来我们会为您详细讲解处理函数 `_process_train` 的功能,同时也将通过实践展示关于 `tokenizer` 的更多功能,让您更加深入地了解自然语言处理任务。首先让我们向 `tokenizer` 输入一条数据(以列表的形式):"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2\n",
+      "dict_keys(['offset_mapping', 'input_ids', 'token_type_ids', 'overflow_to_sample'])\n"
+     ]
+    }
+   ],
+   "source": [
+    "result = tokenizer(\n",
+    "    [train_dataset[0][\"question\"]],\n",
+    "    [train_dataset[0][\"context\"]],\n",
+    "    stride=128,\n",
+    "    max_length=256,\n",
+    "    padding=\"max_length\",\n",
+    "    return_dict=False\n",
+    ")\n",
+    "\n",
+    "print(len(result))\n",
+    "print(result[0].keys())"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "首先不难理解的是,模型必须要同时接受问题(`question`)和上下文(`context`)才能够进行阅读理解,因此我们需要将二者同时进行分词(`tokenize`)。所幸,`Tokenizer` 提供了这一功能,当我们调用 `tokenizer` 的时候,其第一个参数名为 `text`,第二个参数名为 `text_pair`,这使得我们可以同时对一对文本进行分词。同时,`tokenizer` 还需要标记出一条数据中哪些属于问题,哪些属于上下文,这一功能则由 `token_type_ids` 完成。`token_type_ids` 会将输入的第一个文本(问题)标记为 `0`,第二个文本(上下文)标记为 `1`,这样模型在训练时便可以将问题和上下文区分开来:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[1, 1034, 1189, 734, 2003, 241, 284, 131, 553, 271, 28, 125, 280, 2, 131, 1773, 271, 1097, 373, 1427, 1427, 501, 88, 662, 1906, 4, 561, 125, 311, 1168, 311, 692, 46, 430, 4, 84, 2073, 14, 1264, 3967, 5, 1034, 1020, 1829, 268, 4, 373, 539, 8, 154, 5210, 4, 105, 167, 59, 69, 685, 12043, 539, 8, 883, 1020, 4, 29, 720, 95, 90, 427, 67, 262, 5, 384, 266, 14, 101, 59, 789, 416, 237, 12043, 1097, 373, 616, 37, 1519, 93, 61, 15, 4, 255, 535, 7, 1529, 619, 187, 4, 62, 154, 451, 149, 12043, 539, 8, 253, 223, 3679, 323, 523, 4, 535, 34, 87, 8, 203, 280, 1186, 340, 9, 1097, 373, 5, 262, 203, 623, 704, 12043, 84, 2073, 1137, 358, 334, 702, 5, 262, 203, 4, 334, 702, 405, 360, 653, 129, 178, 7, 568, 28, 15, 125, 280, 518, 9, 1179, 487, 12043, 84, 2073, 1621, 1829, 1034, 1020, 4, 539, 8, 448, 91, 202, 466, 70, 262, 4, 638, 125, 280, 83, 299, 12043, 539, 8, 61, 45, 7, 1537, 176, 4, 84, 2073, 288, 39, 4, 889, 280, 14, 125, 280, 156, 538, 12043, 190, 889, 280, 71, 109, 124, 93, 292, 889, 46, 1248, 4, 518, 48, 883, 125, 12043, 539, 8, 268, 889, 280, 109, 270, 4, 1586, 845, 7, 669, 199, 5, 3964, 3740, 1084, 4, 255, 440, 616, 154, 72, 71, 109, 12043, 49, 61, 283, 3591, 34, 87, 297, 41, 9, 1993, 2602, 518, 52, 706, 109, 2]\n",
+      "['[CLS]', '仙', '剑', '奇', '侠', '传', '3', '第', '几', '集', '上', '天', '界', '[SEP]', '第', '35', '集', '雪', '见', '缓', '缓', '张', '开', '眼', '睛', ',', '景', '天', '又', '惊', '又', '喜', '之', '际', ',', '长', '卿', '和', '紫', '萱', '的', '仙', '船', '驶', '至', ',', '见', '众', '人', '无', '恙', ',', '也', '十', '分', '高', '兴', '。', '众', '人', '登', '船', ',', '用', '尽', '合', '力', '把', '自', '身', '的', '真', '气', '和', '水', '分', '输', '给', '她', '。', '雪', '见', '终', '于', '醒', '过', '来', '了', ',', '但', '却', '一', '脸', '木', '然', ',', '全', '无', '反', '应', '。', '众', '人', '向', '常', '胤', '求', '助', ',', '却', '发', '现', '人', '世', '界', '竟', '没', '有', '雪', '见', '的', '身', '世', '纪', '录', '。', '长', '卿', '询', '问', '清', '微', '的', '身', '世', ',', '清', '微', '语', '带', '双', '关', '说', '一', '切', '上', '了', '天', '界', '便', '有', '答', '案', '。', '长', '卿', '驾', '驶', '仙', '船', ',', '众', '人', '决', '定', '立', '马', '动', '身', ',', '往', '天', '界', '而', '去', '。', '众', '人', '来', '到', '一', '荒', '山', ',', '长', '卿', '指', '出', ',', '魔', '界', '和', '天', '界', '相', '连', '。', '由', '魔', '界', '进', '入', '通', '过', '神', '魔', '之', '井', ',', '便', '可', '登', '天', '。', '众', '人', '至', '魔', '界', '入', '口', ',', '仿', '若', '一', '黑', '色', '的', '蝙', '蝠', '洞', ',', '但', '始', '终', '无', '法', '进', '入', '。', '后', '来', '花', '楹', '发', '现', '只', '要', '有', '翅', '膀', '便', '能', '飞', '入', '[SEP]']\n",
+      "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(result[0][\"input_ids\"])\n",
+    "print(tokenizer.convert_ids_to_tokens(result[0][\"input_ids\"]))\n",
+    "print(result[0][\"token_type_ids\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "根据上面的输出我们可以看出,`tokenizer` 会将数据开头用 `[CLS]` 标记,用 `[SEP]` 来分割句子。同时,根据 `token_type_ids` 得到的 0、1 串,我们也很容易将问题和上下文区分开。顺带一提,如果一条数据进行了 `padding`,那么这部分会被标记为 `0` 。\n",
+    "\n",
+    "在输出的 `keys` 中还有一项名为 `offset_mapping` 的键。该项数据能够表示分词后的每个 `token` 在原文中对应文字或词语的位置。比如我们可以像下面这样将数据打印出来:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (0, 0), (0, 1), (1, 3), (3, 4), (4, 5), (5, 6), (6, 7)]\n",
+      "[1, 1034, 1189, 734, 2003, 241, 284, 131, 553, 271, 28, 125, 280, 2, 131, 1773, 271, 1097, 373, 1427]\n",
+      "['[CLS]', '仙', '剑', '奇', '侠', '传', '3', '第', '几', '集', '上', '天', '界', '[SEP]', '第', '35', '集', '雪', '见', '缓']\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(result[0][\"offset_mapping\"][:20])\n",
+    "print(result[0][\"input_ids\"][:20])\n",
+    "print(tokenizer.convert_ids_to_tokens(result[0][\"input_ids\"])[:20])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "`[CLS]` 由于是 `tokenizer` 自己添加进去用于标记数据的 `token`,因此它在原文中找不到任何对应的词语,所以给出的位置范围就是 `(0, 0)`;第二个 `token` 对应第一个 `“仙”` 字,因此映射的位置就是 `(0, 1)`;同理,后面的 `[SEP]` 也不对应任何文字,映射的位置为 `(0, 0)`;而接下来的 `token` 对应 **上下文** 中的第一个字 `“第”`,映射出的位置为 `(0, 1)`;再后面的 `token` 对应原文中的两个字符 `35`,因此其位置映射为 `(1, 3)` 。通过这种手段,我们可以更方便地获取 `token` 与原文的对应关系。\n",
+    "\n",
+    "最后,您也许会注意到我们获取的 `result` 长度为 2 。这是文本在分词后长度超过了 `max_length` 256 ,`tokenizer` 将数据分成了两部分所致。在阅读理解任务中,我们不可能像文本分类那样轻易地将一条数据截断,因为答案很可能就出现在后面被丢弃的那部分数据中,因此,我们需要保留所有的数据(当然,您也可以直接丢弃这些超长的数据)。`overflow_to_sample` 则可以标识当前数据在原数据的索引:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[CLS]仙剑奇侠传3第几集上天界[SEP]第35集雪见缓缓张开眼睛,景天又惊又喜之际,长卿和紫萱的仙船驶至,见众人无恙,也十分高兴。众人登船,用尽合力把自身的真气和水分输给她。雪见终于醒过来了,但却一脸木然,全无反应。众人向常胤求助,却发现人世界竟没有雪见的身世纪录。长卿询问清微的身世,清微语带双关说一切上了天界便有答案。长卿驾驶仙船,众人决定立马动身,往天界而去。众人来到一荒山,长卿指出,魔界和天界相连。由魔界进入通过神魔之井,便可登天。众人至魔界入口,仿若一黑色的蝙蝠洞,但始终无法进入。后来花楹发现只要有翅膀便能飞入[SEP]\n",
+      "overflow_to_sample:  0\n",
+      "[CLS]仙剑奇侠传3第几集上天界[SEP]说一切上了天界便有答案。长卿驾驶仙船,众人决定立马动身,往天界而去。众人来到一荒山,长卿指出,魔界和天界相连。由魔界进入通过神魔之井,便可登天。众人至魔界入口,仿若一黑色的蝙蝠洞,但始终无法进入。后来花楹发现只要有翅膀便能飞入。于是景天等人打下许多乌鸦,模仿重楼的翅膀,制作数对翅膀状巨物。刚佩戴在身,便被吸入洞口。众人摔落在地,抬头发现魔界守卫。景天和众魔套交情,自称和魔尊重楼相熟,众魔不理,打了起来。[SEP][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD][PAD]\n",
+      "overflow_to_sample:  0\n"
+     ]
+    }
+   ],
+   "source": [
+    "for res in result:\n",
+    "    tokens = tokenizer.convert_ids_to_tokens(res[\"input_ids\"])\n",
+    "    print(\"\".join(tokens))\n",
+    "    print(\"overflow_to_sample: \", res[\"overflow_to_sample\"])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "将两条数据均输出之后可以看到,它们都出自我们传入的数据,并且存在一部分重合。`tokenizer` 的 `stride` 参数可以设置重合部分的长度,这也可以帮助模型识别被分割开的两条数据;`overflow_to_sample` 的 `0` 则代表它们来自于第 `0` 条数据。\n",
+    "\n",
+    "基于以上信息,我们处理训练集的思路如下:\n",
+    "\n",
+    "1. 通过 `overflow_to_sample` 来获取原来的数据\n",
+    "2. 通过原数据的 `answers` 找到答案的起始位置\n",
+    "3. 通过 `offset_mapping` 给出的映射关系在分词处理后的数据中找到答案的起始位置,分别记录在 `start_pos` 和 `end_pos` 中;如果没有找到答案(比如答案被截断了),那么答案的起始位置就被标记为 `[CLS]` 的位置。\n",
+    "\n",
+    "这样 `_process_train` 函数就呼之欲出了,我们调用 `train_dataset.map` 函数,并将 `batched` 参数设置为 `True` ,将所有数据批量地进行更新。有一点需要注意的是,**在处理过后数据量会增加**。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'offset_mapping': [(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (0, 0), (0, 1), (1, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (31, 32), (32, 33), (33, 34), (34, 35), (35, 36), (36, 37), (37, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), (49, 50), (50, 51), (51, 52), (52, 53), (53, 54), (54, 55), (55, 56), (56, 57), (57, 58), (58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66), (66, 67), (67, 68), (68, 69), (69, 70), (70, 71), (71, 72), (72, 73), (73, 74), (74, 75), (75, 76), (76, 77), (77, 78), (78, 79), (79, 80), (80, 81), (81, 82), (82, 83), (83, 84), (84, 85), (85, 86), (86, 87), (87, 88), (88, 89), (89, 90), (90, 91), (91, 92), (92, 93), (93, 94), (94, 95), (95, 96), (96, 97), (97, 98), (98, 99), (99, 100), (100, 101), (101, 102), (102, 103), (103, 104), (104, 105), (105, 106), (106, 107), (107, 108), (108, 109), (109, 110), (110, 111), (111, 112), (112, 113), (113, 114), (114, 115), (115, 116), (116, 117), (117, 118), (118, 119), (119, 120), (120, 121), (121, 122), (122, 123), (123, 124), (124, 125), (125, 126), (126, 127), (127, 128), (128, 129), (129, 130), (130, 131), (131, 132), (132, 133), (133, 134), (134, 135), (135, 136), (136, 137), (137, 138), (138, 139), (139, 140), (140, 141), (141, 142), (142, 143), (143, 144), (144, 145), (145, 146), (146, 147), (147, 148), (148, 149), (149, 150), (150, 151), (151, 152), (152, 153), (153, 154), (154, 155), (155, 156), (156, 157), (157, 158), (158, 159), (159, 160), (160, 161), (161, 162), (162, 163), (163, 164), (164, 165), (165, 166), (166, 167), (167, 168), (168, 169), (169, 170), (170, 171), (171, 172), (172, 173), (173, 174), (174, 175), (175, 176), (176, 177), (177, 178), (178, 179), (179, 180), (180, 181), (181, 182), (182, 183), (183, 184), (184, 185), (185, 186), (186, 187), (187, 188), (188, 189), (189, 190), (190, 191), (191, 192), (192, 193), (193, 194), (194, 195), (195, 196), (196, 197), (197, 198), (198, 199), (199, 200), (200, 201), (201, 202), (202, 203), (203, 204), (204, 205), (205, 206), (206, 207), (207, 208), (208, 209), (209, 210), (210, 211), (211, 212), (212, 213), (213, 214), (214, 215), (215, 216), (216, 217), (217, 218), (218, 219), (219, 220), (220, 221), (221, 222), (222, 223), (223, 224), (224, 225), (225, 226), (226, 227), (227, 228), (228, 229), (229, 230), (230, 231), (231, 232), (232, 233), (233, 234), (234, 235), (235, 236), (236, 237), (237, 238), (238, 239), (239, 240), (240, 241), (241, 242), (0, 0)], 'input_ids': [1, 1034, 1189, 734, 2003, 241, 284, 131, 553, 271, 28, 125, 280, 2, 131, 1773, 271, 1097, 373, 1427, 1427, 501, 88, 662, 1906, 4, 561, 125, 311, 1168, 311, 692, 46, 430, 4, 84, 2073, 14, 1264, 3967, 5, 1034, 1020, 1829, 268, 4, 373, 539, 8, 154, 5210, 4, 105, 167, 59, 69, 685, 12043, 539, 8, 883, 1020, 4, 29, 720, 95, 90, 427, 67, 262, 5, 384, 266, 14, 101, 59, 789, 416, 237, 12043, 1097, 373, 616, 37, 1519, 93, 61, 15, 4, 255, 535, 7, 1529, 619, 187, 4, 62, 154, 451, 149, 12043, 539, 8, 253, 223, 3679, 323, 523, 4, 535, 34, 87, 8, 203, 280, 1186, 340, 9, 1097, 373, 5, 262, 203, 623, 704, 12043, 84, 2073, 1137, 358, 334, 702, 5, 262, 203, 4, 334, 702, 405, 360, 653, 129, 178, 7, 568, 28, 15, 125, 280, 518, 9, 1179, 487, 12043, 84, 2073, 1621, 1829, 1034, 1020, 4, 539, 8, 448, 91, 202, 466, 70, 262, 4, 638, 125, 280, 83, 299, 12043, 539, 8, 61, 45, 7, 1537, 176, 4, 84, 2073, 288, 39, 4, 889, 280, 14, 125, 280, 156, 538, 12043, 190, 889, 280, 71, 109, 124, 93, 292, 889, 46, 1248, 4, 518, 48, 883, 125, 12043, 539, 8, 268, 889, 280, 109, 270, 4, 1586, 845, 7, 669, 199, 5, 3964, 3740, 1084, 4, 255, 440, 616, 154, 72, 71, 109, 12043, 49, 61, 283, 3591, 34, 87, 297, 41, 9, 1993, 2602, 518, 52, 706, 109, 2], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'overflow_to_sample': 0, 'start_pos': 14, 'end_pos': 16}\n",
+      "处理后的训练集大小: 26198\n"
+     ]
+    }
+   ],
+   "source": [
+    "max_length = 256\n",
+    "doc_stride = 128\n",
+    "def _process_train(data):\n",
+    "\n",
+    "    contexts = [data[i][\"context\"] for i in range(len(data))]\n",
+    "    questions = [data[i][\"question\"] for i in range(len(data))]\n",
+    "\n",
+    "    tokenized_data_list = tokenizer(\n",
+    "        questions,\n",
+    "        contexts,\n",
+    "        stride=doc_stride,\n",
+    "        max_length=max_length,\n",
+    "        padding=\"max_length\",\n",
+    "        return_dict=False\n",
+    "    )\n",
+    "\n",
+    "    for i, tokenized_data in enumerate(tokenized_data_list):\n",
+    "        # 获取 [CLS] 对应的位置\n",
+    "        input_ids = tokenized_data[\"input_ids\"]\n",
+    "        cls_index = input_ids.index(tokenizer.cls_token_id)\n",
+    "\n",
+    "        # 在 tokenize 的过程中,汉字和 token 在位置上并非一一对应的\n",
+    "        # 而 offset mapping 记录了每个 token 在原文中对应的起始位置\n",
+    "        offsets = tokenized_data[\"offset_mapping\"]\n",
+    "        # token_type_ids 记录了一条数据中哪些是问题,哪些是上下文\n",
+    "        token_type_ids = tokenized_data[\"token_type_ids\"]\n",
+    "\n",
+    "        # 一条数据可能因为长度过长而在 tokenized_data 中存在多个结果\n",
+    "        # overflow_to_sample 表示了当前 tokenize_example 属于 data 中的哪一条数据\n",
+    "        sample_index = tokenized_data[\"overflow_to_sample\"]\n",
+    "        answers = data[sample_index][\"answers\"]\n",
+    "\n",
+    "        # answers 和 answer_starts 均为长度为 1 的 list\n",
+    "        # 我们可以计算出答案的结束位置\n",
+    "        start_char = answers[\"answer_start\"][0]\n",
+    "        end_char = start_char + len(answers[\"text\"][0])\n",
+    "\n",
+    "        token_start_index = 0\n",
+    "        while token_type_ids[token_start_index] != 1:\n",
+    "            token_start_index += 1\n",
+    "\n",
+    "        token_end_index = len(input_ids) - 1\n",
+    "        while token_type_ids[token_end_index] != 1:\n",
+    "            token_end_index -= 1\n",
+    "        # 分词后一条数据的结尾一定是 [SEP],因此还需要减一\n",
+    "        token_end_index -= 1\n",
+    "\n",
+    "        if not (offsets[token_start_index][0] <= start_char and\n",
+    "                offsets[token_end_index][1] >= end_char):\n",
+    "            # 如果答案不在这条数据中,则将答案位置标记为 [CLS] 的位置\n",
+    "            tokenized_data_list[i][\"start_pos\"] = cls_index\n",
+    "            tokenized_data_list[i][\"end_pos\"] = cls_index\n",
+    "        else:\n",
+    "            # 否则,我们可以找到答案对应的 token 的起始位置,记录在 start_pos 和 end_pos 中\n",
+    "            while token_start_index < len(offsets) and offsets[\n",
+    "                    token_start_index][0] <= start_char:\n",
+    "                token_start_index += 1\n",
+    "            tokenized_data_list[i][\"start_pos\"] = token_start_index - 1\n",
+    "            while offsets[token_end_index][1] >= end_char:\n",
+    "                token_end_index -= 1\n",
+    "            tokenized_data_list[i][\"end_pos\"] = token_end_index + 1\n",
+    "\n",
+    "    return tokenized_data_list\n",
+    "\n",
+    "train_dataset.map(_process_train, batched=True, num_workers=5)\n",
+    "print(train_dataset[0])\n",
+    "print(\"处理后的训练集大小:\", len(train_dataset))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 2.2 处理验证集\n",
+    "\n",
+    "对于验证集的处理则简单得多,我们只需要保存原数据的 `id` 并将 `offset_mapping` 中不属于上下文的部分设置为 `None` 即可。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       ""
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "def _process_val(data):\n",
+    "\n",
+    "    contexts = [data[i][\"context\"] for i in range(len(data))]\n",
+    "    questions = [data[i][\"question\"] for i in range(len(data))]\n",
+    "\n",
+    "    tokenized_data_list = tokenizer(\n",
+    "        questions,\n",
+    "        contexts,\n",
+    "        stride=doc_stride,\n",
+    "        max_length=max_length,\n",
+    "        return_dict=False\n",
+    "    )\n",
+    "\n",
+    "    for i, tokenized_data in enumerate(tokenized_data_list):\n",
+    "        token_type_ids = tokenized_data[\"token_type_ids\"]\n",
+    "        # 保存数据对应的 id\n",
+    "        sample_index = tokenized_data[\"overflow_to_sample\"]\n",
+    "        tokenized_data_list[i][\"example_id\"] = data[sample_index][\"id\"]\n",
+    "\n",
+    "        # 将不属于 context 的 offset 设置为 None\n",
+    "        tokenized_data_list[i][\"offset_mapping\"] = [\n",
+    "            (o if token_type_ids[k] == 1 else None)\n",
+    "            for k, o in enumerate(tokenized_data[\"offset_mapping\"])\n",
+    "        ]\n",
+    "\n",
+    "    return tokenized_data_list\n",
+    "\n",
+    "val_dataset.map(_process_val, batched=True, num_workers=5)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### 2.3 DataLoader\n",
+    "\n",
+    "最后使用 `PaddleDataLoader` 将数据集包裹起来即可。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from fastNLP.core import PaddleDataLoader\n", + "\n", + "train_dataloader = PaddleDataLoader(train_dataset, batch_size=32, shuffle=True)\n", + "val_dataloader = PaddleDataLoader(val_dataset, batch_size=16)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. 模型训练:自己定义评测用的 Metric 实现更加自由的任务评测\n", + "\n", + "#### 3.1 损失函数\n", + "\n", + "对于阅读理解任务,我们使用的是 `ErnieForQuestionAnswering` 模型。该模型在接受输入后会返回两个值:`start_logits` 和 `end_logits` ,大小均为 `(batch_size, sequence_length)`,反映了每条数据每个词语为答案起始位置的可能性,因此我们需要自定义一个损失函数来计算 `loss`。 `CrossEntropyLossForSquad` 会分别对答案起始位置的预测值和真实值计算交叉熵,最后返回其平均值作为最终的损失。" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "class CrossEntropyLossForSquad(paddle.nn.Layer):\n", + " def __init__(self):\n", + " super(CrossEntropyLossForSquad, self).__init__()\n", + "\n", + " def forward(self, start_logits, end_logits, start_pos, end_pos):\n", + " start_pos = paddle.unsqueeze(start_pos, axis=-1)\n", + " end_pos = paddle.unsqueeze(end_pos, axis=-1)\n", + " start_loss = paddle.nn.functional.softmax_with_cross_entropy(\n", + " logits=start_logits, label=start_pos)\n", + " start_loss = paddle.mean(start_loss)\n", + " end_loss = paddle.nn.functional.softmax_with_cross_entropy(\n", + " logits=end_logits, label=end_pos)\n", + " end_loss = paddle.mean(end_loss)\n", + "\n", + " loss = (start_loss + end_loss) / 2\n", + " return loss" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3.2 定义模型\n", + "\n", + "模型的核心则是 `ErnieForQuestionAnswering` 的 `ernie-1.0-base-zh` 预训练模型,同时按照 `fastNLP` 的规定定义 `train_step` 和 `evaluate_step` 函数。这里 `evaluate_step` 函数并没有像文本分类那样直接返回该批次数据的评测结果,这一点我们将在下面为您讲解。" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m[2022-06-27 19:00:15,825] [ INFO]\u001b[0m - Already cached /remote-home/shxing/.paddlenlp/models/ernie-1.0-base-zh/ernie_v1_chn_base.pdparams\u001b[0m\n", + "W0627 19:00:15.831080 21543 gpu_context.cc:278] Please NOTE: device: 0, GPU Compute Capability: 7.5, Driver API Version: 11.2, Runtime API Version: 11.2\n", + "W0627 19:00:15.843276 21543 gpu_context.cc:306] device: 0, cuDNN Version: 8.1.\n" + ] + } + ], + "source": [ + "from paddlenlp.transformers import ErnieForQuestionAnswering\n", + "\n", + "class QAModel(paddle.nn.Layer):\n", + " def __init__(self, model_checkpoint):\n", + " super(QAModel, self).__init__()\n", + " self.model = ErnieForQuestionAnswering.from_pretrained(model_checkpoint)\n", + " self.loss_func = CrossEntropyLossForSquad()\n", + "\n", + " def forward(self, input_ids, token_type_ids):\n", + " start_logits, end_logits = self.model(input_ids, token_type_ids)\n", + " return start_logits, end_logits\n", + "\n", + " def train_step(self, input_ids, token_type_ids, start_pos, end_pos):\n", + " start_logits, end_logits = self(input_ids, token_type_ids)\n", + " loss = self.loss_func(start_logits, end_logits, start_pos, end_pos)\n", + " return {\"loss\": loss}\n", + "\n", + " def evaluate_step(self, input_ids, token_type_ids):\n", + " start_logits, end_logits = self(input_ids, token_type_ids)\n", + " return {\"start_logits\": start_logits, \"end_logits\": end_logits}\n", + "\n", + "model = QAModel(MODEL_NAME)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3.3 自定义 Metric 进行数据的评估\n", + "\n", + "`paddlenlp` 为我们提供了评测 `SQuAD` 格式数据集的函数 `compute_prediction` 和 `squad_evaluate`:\n", + "- `compute_prediction` 函数要求传入原数据 `examples` 、处理后的数据 `features` 和 `features` 对应的结果 `predictions`(一个包含所有数据 `start_logits` 和 `end_logits` 的元组)\n", + "- `squad_evaluate` 要求传入原数据 `examples` 和预测结果 `all_predictions`(通常来自于 `compute_prediction`)\n", + "\n", + "在使用这两个函数的时候,我们需要向其中传入数据集,但显然根据 `fastNLP` 的设计,我们无法在 `evaluate_step` 里实现这一过程,并且 `fastNLP` 也并没有提供计算 `F1` 和 `EM` 的 `Metric`,故我们需要自己定义用于评测的 `Metric`。\n", + "\n", + "在初始化之外,一个 `Metric` 还需要实现三个函数:\n", + "\n", + "1. `reset` - 该函数会在验证数据集的迭代之前被调用,用于清空数据;在我们自定义的 `Metric` 中,我们需要将 `all_start_logits` 和 `all_end_logits` 清空,重新收集每个 `batch` 的结果。\n", + "2. `update` - 该函数会在在每个 `batch` 得到结果后被调用,用于更新 `Metric` 的状态;它的参数即为 `evaluate_step` 返回的内容。我们在这里将得到的 `start_logits` 和 `end_logits` 收集起来。\n", + "3. `get_metric` - 该函数会在数据集被迭代完毕后调用,用于计算评测的结果。现在我们有了整个验证集的 `all_start_logits` 和 `all_end_logits` ,将他们传入 `compute_predictions` 函数得到预测的结果,并继续使用 `squad_evaluate` 函数得到评测的结果。\n", + " - 注:`suqad_evaluate` 函数会自己输出评测结果,为了不让其干扰 `fastNLP` 输出,这里我们使用 `contextlib.redirect_stdout(None)` 将函数的标准输出屏蔽掉。\n", + "\n", + "综上,`SquadEvaluateMetric` 实现的评估过程是:将验证集中所有数据的 `logits` 收集起来,然后统一传入 `compute_prediction` 和 `squad_evaluate` 中进行评估。值得一提的是,`paddlenlp.datasets.load_dataset` 返回的结果是一个 `MapDataset` 类型,其 `data` 成员为加载时的数据,`new_data` 为经过 `map` 函数处理后更新的数据,因此可以分别作为 `examples` 和 `features` 传入。" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP.core import Metric\n", + "from paddlenlp.metrics.squad import squad_evaluate, compute_prediction\n", + "import contextlib\n", + "\n", + "class SquadEvaluateMetric(Metric):\n", + " def __init__(self, examples, features, testing=False):\n", + " super(SquadEvaluateMetric, self).__init__(\"paddle\", False)\n", + " self.examples = examples\n", + " self.features = features\n", + " self.all_start_logits = []\n", + " self.all_end_logits = []\n", + " self.testing = testing\n", + "\n", + " def reset(self):\n", + " self.all_start_logits = []\n", + " self.all_end_logits = []\n", + "\n", + " def update(self, start_logits, end_logits):\n", + " for start, end in zip(start_logits, end_logits):\n", + " self.all_start_logits.append(start.numpy())\n", + " self.all_end_logits.append(end.numpy())\n", + "\n", + " def get_metric(self):\n", + " all_predictions, _, _ = compute_prediction(\n", + " self.examples, self.features[:len(self.all_start_logits)],\n", + " (self.all_start_logits, self.all_end_logits),\n", + " False, 20, 30\n", + " )\n", + " with contextlib.redirect_stdout(None):\n", + " result = squad_evaluate(\n", + " examples=self.examples,\n", + " preds=all_predictions,\n", + " is_whitespace_splited=False\n", + " )\n", + "\n", + " if self.testing:\n", + " self.print_predictions(all_predictions)\n", + " return result\n", + "\n", + " def print_predictions(self, preds):\n", + " for i, data in enumerate(self.examples):\n", + " if i >= 5:\n", + " break\n", + " print()\n", + " print(\"原文:\", data[\"context\"])\n", + " print(\"问题:\", data[\"question\"], \\\n", + " \"答案:\", preds[data[\"id\"]], \\\n", + " \"正确答案:\", data[\"answers\"][\"text\"])\n", + "\n", + "metric = SquadEvaluateMetric(\n", + " val_dataloader.dataset.data,\n", + " val_dataloader.dataset.new_data,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3.4 训练\n", + "\n", + "至此所有的准备工作已经完成,可以使用 `Trainer` 进行训练了。学习率我们依旧采用线性预热策略 `LinearDecayWithWarmup`,优化器为 `AdamW`;回调模块我们选择 `LRSchedCallback` 更新学习率和 `LoadBestModelCallback` 监视评测结果的 `f1` 分数。初始化好 `Trainer` 之后,就将训练的过程交给 `fastNLP` 吧。" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[19:04:54] INFO     Running evaluator sanity check for 2 batches.              trainer.py:631\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[19:04:54]\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=367046;file://../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=96810;file://../fastNLP/core/controllers/trainer.py#631\u001b\\\u001b[2m631\u001b[0m\u001b]8;;\u001b\\\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" + }, + { + "data": { + "text/html": [ + "
---------------------------- Eval. results on Epoch:0, Batch:100 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m100\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 49.25899788285109,\n",
+       "  \"f1#squad\": 66.55559127349602,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 49.25899788285109,\n",
+       "  \"HasAns_f1#squad\": 66.55559127349602,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m49.25899788285109\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m66.55559127349602\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m49.25899788285109\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m66.55559127349602\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:200 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m200\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 57.37473535638673,\n",
+       "  \"f1#squad\": 70.93036525200617,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 57.37473535638673,\n",
+       "  \"HasAns_f1#squad\": 70.93036525200617,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m57.37473535638673\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m70.93036525200617\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m57.37473535638673\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m70.93036525200617\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:300 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m300\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 63.86732533521524,\n",
+       "  \"f1#squad\": 78.62546663568186,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 63.86732533521524,\n",
+       "  \"HasAns_f1#squad\": 78.62546663568186,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m63.86732533521524\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m78.62546663568186\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m63.86732533521524\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m78.62546663568186\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:400 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m400\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 64.92589978828511,\n",
+       "  \"f1#squad\": 79.36746074079691,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 64.92589978828511,\n",
+       "  \"HasAns_f1#squad\": 79.36746074079691,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m64.92589978828511\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m79.36746074079691\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m64.92589978828511\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m79.36746074079691\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:500 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m500\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 65.70218772053634,\n",
+       "  \"f1#squad\": 80.33295482054824,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 65.70218772053634,\n",
+       "  \"HasAns_f1#squad\": 80.33295482054824,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m65.70218772053634\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m80.33295482054824\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m65.70218772053634\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m80.33295482054824\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:600 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m600\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 65.41990119971771,\n",
+       "  \"f1#squad\": 79.7483487059053,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 65.41990119971771,\n",
+       "  \"HasAns_f1#squad\": 79.7483487059053,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m65.41990119971771\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m79.7483487059053\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m65.41990119971771\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m79.7483487059053\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:700 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m700\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 66.61961891319689,\n",
+       "  \"f1#squad\": 80.32432238994133,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 66.61961891319689,\n",
+       "  \"HasAns_f1#squad\": 80.32432238994133,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m66.61961891319689\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m80.32432238994133\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m66.61961891319689\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m80.32432238994133\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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:0, Batch:800 ----------------------------\n",
+       "
\n" + ], + "text/plain": [ + "---------------------------- Eval. results on Epoch:\u001b[1;36m0\u001b[0m, Batch:\u001b[1;36m800\u001b[0m ----------------------------\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
{\n",
+       "  \"exact#squad\": 65.84333098094567,\n",
+       "  \"f1#squad\": 79.23169801265415,\n",
+       "  \"total#squad\": 1417,\n",
+       "  \"HasAns_exact#squad\": 65.84333098094567,\n",
+       "  \"HasAns_f1#squad\": 79.23169801265415,\n",
+       "  \"HasAns_total#squad\": 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"exact#squad\"\u001b[0m: \u001b[1;36m65.84333098094567\u001b[0m,\n", + " \u001b[1;34m\"f1#squad\"\u001b[0m: \u001b[1;36m79.23169801265415\u001b[0m,\n", + " \u001b[1;34m\"total#squad\"\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[1;34m\"HasAns_exact#squad\"\u001b[0m: \u001b[1;36m65.84333098094567\u001b[0m,\n", + " \u001b[1;34m\"HasAns_f1#squad\"\u001b[0m: \u001b[1;36m79.23169801265415\u001b[0m,\n", + " \u001b[1;34m\"HasAns_total#squad\"\u001b[0m: \u001b[1;36m1417\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" + }, + { + "data": { + "text/html": [ + "
[19:20:28] INFO     Loading best model from fnlp-ernie-squad/ load_best_model_callback.py:111\n",
+       "                    2022-06-27-19_00_15_388554/best_so_far                                   \n",
+       "                    with f1#squad: 80.33295482054824...                                      \n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[19:20:28]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Loading best model from fnlp-ernie-squad/ \u001b]8;id=163935;file://../fastNLP/core/callbacks/load_best_model_callback.py\u001b\\\u001b[2mload_best_model_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=31503;file://../fastNLP/core/callbacks/load_best_model_callback.py#111\u001b\\\u001b[2m111\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m \u001b[1;36m2022\u001b[0m-\u001b[1;36m06\u001b[0m-\u001b[1;36m27\u001b[0m-19_00_15_388554/best_so_far \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m with f1#squad: \u001b[1;36m80.33295482054824\u001b[0m\u001b[33m...\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           INFO     Deleting fnlp-ernie-squad/2022-06-27-19_0 load_best_model_callback.py:131\n",
+       "                    0_15_388554/best_so_far...                                               \n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Deleting fnlp-ernie-squad/\u001b[1;36m2022\u001b[0m-\u001b[1;36m06\u001b[0m-\u001b[1;36m27\u001b[0m-19_0 \u001b]8;id=560859;file://../fastNLP/core/callbacks/load_best_model_callback.py\u001b\\\u001b[2mload_best_model_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=573263;file://../fastNLP/core/callbacks/load_best_model_callback.py#131\u001b\\\u001b[2m131\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m 0_15_388554/best_so_far\u001b[33m...\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from fastNLP import Trainer, LRSchedCallback, LoadBestModelCallback\n", + "from paddlenlp.transformers import LinearDecayWithWarmup\n", + "\n", + "n_epochs = 1\n", + "num_training_steps = len(train_dataloader) * n_epochs\n", + "lr_scheduler = LinearDecayWithWarmup(3e-5, num_training_steps, 0.1)\n", + "optimizer = paddle.optimizer.AdamW(\n", + " learning_rate=lr_scheduler,\n", + " parameters=model.parameters(),\n", + ")\n", + "callbacks=[\n", + " LRSchedCallback(lr_scheduler, step_on=\"batch\"),\n", + " LoadBestModelCallback(\"f1#squad\", larger_better=True, save_folder=\"fnlp-ernie-squad\")\n", + "]\n", + "trainer = Trainer(\n", + " model=model,\n", + " train_dataloader=train_dataloader,\n", + " evaluate_dataloaders=val_dataloader,\n", + " device=1,\n", + " optimizers=optimizer,\n", + " n_epochs=n_epochs,\n", + " callbacks=callbacks,\n", + " evaluate_every=100,\n", + " metrics={\"squad\": metric},\n", + ")\n", + "trainer.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3.5 测试\n", + "\n", + "最后,我们可以使用 `Evaluator` 查看我们训练的结果。我们在之前为 `SquadEvaluateMetric` 设置了 `testing` 参数来在测试阶段进行输出,可以看到,训练的结果还是比较不错的。" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
原文: 爬行垫根据中间材料的不同可以分为:XPE爬行垫、EPE爬行垫、EVA爬行垫、PVC爬行垫;其中XPE爬\n",
+       "行垫、EPE爬行垫都属于PE材料加保鲜膜复合而成,都是无异味的环保材料,但是XPE爬行垫是品质较好的爬\n",
+       "行垫,韩国进口爬行垫都是这种爬行垫,而EPE爬行垫是国内厂家为了减低成本,使用EPE(珍珠棉)作为原料生\n",
+       "产的一款爬行垫,该材料弹性差,易碎,开孔发泡防水性弱。EVA爬行垫、PVC爬行垫是用EVA或PVC作为原材料\n",
+       "与保鲜膜复合的而成的爬行垫,或者把图案转印在原材料上,这两款爬行垫通常有异味,如果是图案转印的爬\n",
+       "行垫,油墨外露容易脱落。 \n",
+       "当时我儿子爬的时候,我们也买了垫子,但是始终有味。最后就没用了,铺的就的薄毯子让他爬。\n",
+       "
\n" + ], + "text/plain": [ + "原文: 爬行垫根据中间材料的不同可以分为:XPE爬行垫、EPE爬行垫、EVA爬行垫、PVC爬行垫;其中XPE爬\n", + "行垫、EPE爬行垫都属于PE材料加保鲜膜复合而成,都是无异味的环保材料,但是XPE爬行垫是品质较好的爬\n", + "行垫,韩国进口爬行垫都是这种爬行垫,而EPE爬行垫是国内厂家为了减低成本,使用EPE(珍珠棉)作为原料生\n", + "产的一款爬行垫,该材料弹性差,易碎,开孔发泡防水性弱。EVA爬行垫、PVC爬行垫是用EVA或PVC作为原材料\n", + "与保鲜膜复合的而成的爬行垫,或者把图案转印在原材料上,这两款爬行垫通常有异味,如果是图案转印的爬\n", + "行垫,油墨外露容易脱落。 \n", + "当时我儿子爬的时候,我们也买了垫子,但是始终有味。最后就没用了,铺的就的薄毯子让他爬。\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
问题: 爬行垫什么材质的好 答案: EPE(珍珠棉 正确答案: ['XPE']\n",
+       "
\n" + ], + "text/plain": [ + "问题: 爬行垫什么材质的好 答案: EPE(珍珠棉 正确答案: ['XPE']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
原文: 真实情况是160-162。她平时谎报的168是因为不离脚穿高水台恨天高(15厘米) 图1她穿着高水台恨\n",
+       "天高和刘亦菲一样高,(刘亦菲对外报身高172)范冰冰礼服下厚厚的高水台暴露了她的心机,对比一下两者的\n",
+       "鞋子吧 图2 穿着高水台恨天高才和刘德华谢霆锋持平,如果她真的有168,那么加上鞋高,刘和谢都要有180?\n",
+       "明显是不可能的。所以刘德华对外报的身高174减去10-15厘米才是范冰冰的真实身高 图3,范冰冰有一次脱\n",
+       "鞋上场,这个最说明问题了,看看她的身体比例吧。还有目测一下她手上鞋子的鞋跟有多高多厚吧,至少超过\n",
+       "10厘米。\n",
+       "
\n" + ], + "text/plain": [ + "原文: 真实情况是160-162。她平时谎报的168是因为不离脚穿高水台恨天高(15厘米) 图1她穿着高水台恨\n", + "天高和刘亦菲一样高,(刘亦菲对外报身高172)范冰冰礼服下厚厚的高水台暴露了她的心机,对比一下两者的\n", + "鞋子吧 图2 穿着高水台恨天高才和刘德华谢霆锋持平,如果她真的有168,那么加上鞋高,刘和谢都要有180?\n", + "明显是不可能的。所以刘德华对外报的身高174减去10-15厘米才是范冰冰的真实身高 图3,范冰冰有一次脱\n", + "鞋上场,这个最说明问题了,看看她的身体比例吧。还有目测一下她手上鞋子的鞋跟有多高多厚吧,至少超过\n", + "10厘米。\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
问题: 范冰冰多高真实身高 答案: 160-162 正确答案: ['160-162']\n",
+       "
\n" + ], + "text/plain": [ + "问题: 范冰冰多高真实身高 答案: 160-162 正确答案: ['160-162']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
原文: 防水作为目前高端手机的标配,特别是苹果也支持防水之后,国产大多数高端旗舰手机都已经支持防\n",
+       "水。虽然我们真的不会故意把手机放入水中,但是有了防水之后,用户心里会多一重安全感。那么近日最为\n",
+       "火热的小米6防水吗?小米6的防水级别又是多少呢? 小编查询了很多资料发现,小米6确实是防水的,但是为\n",
+       "了保持低调,同时为了不被别人说防水等级不够,很多资料都没有标注小米是否防水。根据评测资料显示,小\n",
+       "米6是支持IP68级的防水,是绝对能够满足日常生活中的防水需求的。\n",
+       "
\n" + ], + "text/plain": [ + "原文: 防水作为目前高端手机的标配,特别是苹果也支持防水之后,国产大多数高端旗舰手机都已经支持防\n", + "水。虽然我们真的不会故意把手机放入水中,但是有了防水之后,用户心里会多一重安全感。那么近日最为\n", + "火热的小米6防水吗?小米6的防水级别又是多少呢? 小编查询了很多资料发现,小米6确实是防水的,但是为\n", + "了保持低调,同时为了不被别人说防水等级不够,很多资料都没有标注小米是否防水。根据评测资料显示,小\n", + "米6是支持IP68级的防水,是绝对能够满足日常生活中的防水需求的。\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
问题: 小米6防水等级 答案: IP68级 正确答案: ['IP68级']\n",
+       "
\n" + ], + "text/plain": [ + "问题: 小米6防水等级 答案: IP68级 正确答案: ['IP68级']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
原文: 这位朋友你好,女性出现妊娠反应一般是从6-12周左右,也就是女性怀孕1个多月就会开始出现反应,\n",
+       "第3个月的时候,妊辰反应基本结束。 而大部分女性怀孕初期都会出现恶心、呕吐的感觉,这些症状都是因\n",
+       "人而异的,除非恶心、呕吐的非常厉害,才需要就医,否则这些都是刚怀孕的的正常症状。1-3个月的时候可\n",
+       "以观察一下自己的皮肤,一般女性怀孕初期可能会产生皮肤色素沉淀或是腹壁产生妊娠纹,特别是在怀孕的\n",
+       "后期更加明显。 还有很多女性怀孕初期会出现疲倦、嗜睡的情况。怀孕三个月的时候,膀胱会受到日益胀\n",
+       "大的子宫的压迫,容量会变小,所以怀孕期间也会有尿频的现象出现。月经停止也是刚怀孕最容易出现的症\n",
+       "状,只要是平时月经正常的女性,在性行为后超过正常经期两周,就有可能是怀孕了。 如果你想判断自己是\n",
+       "否怀孕,可以看看自己有没有这些反应。当然这也只是多数人的怀孕表现,也有部分女性怀孕表现并不完全\n",
+       "是这样,如果你无法确定自己是否怀孕,最好去医院检查一下。\n",
+       "
\n" + ], + "text/plain": [ + "原文: 这位朋友你好,女性出现妊娠反应一般是从6-12周左右,也就是女性怀孕1个多月就会开始出现反应,\n", + "第3个月的时候,妊辰反应基本结束。 而大部分女性怀孕初期都会出现恶心、呕吐的感觉,这些症状都是因\n", + "人而异的,除非恶心、呕吐的非常厉害,才需要就医,否则这些都是刚怀孕的的正常症状。1-3个月的时候可\n", + "以观察一下自己的皮肤,一般女性怀孕初期可能会产生皮肤色素沉淀或是腹壁产生妊娠纹,特别是在怀孕的\n", + "后期更加明显。 还有很多女性怀孕初期会出现疲倦、嗜睡的情况。怀孕三个月的时候,膀胱会受到日益胀\n", + "大的子宫的压迫,容量会变小,所以怀孕期间也会有尿频的现象出现。月经停止也是刚怀孕最容易出现的症\n", + "状,只要是平时月经正常的女性,在性行为后超过正常经期两周,就有可能是怀孕了。 如果你想判断自己是\n", + "否怀孕,可以看看自己有没有这些反应。当然这也只是多数人的怀孕表现,也有部分女性怀孕表现并不完全\n", + "是这样,如果你无法确定自己是否怀孕,最好去医院检查一下。\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
问题: 怀孕多久会有反应 答案: 6-12周左右 正确答案: ['6-12周左右', '6-12周', '1个多月']\n",
+       "
\n" + ], + "text/plain": [ + "问题: 怀孕多久会有反应 答案: 6-12周左右 正确答案: ['6-12周左右', '6-12周', '1个多月']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n",
+       "
\n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
原文: 【东奥会计在线——中级会计职称频道推荐】根据《关于提高科技型中小企业研究开发费用税前加计\n",
+       "扣除比例的通知》的规定,研发费加计扣除比例提高到75%。|财政部、国家税务总局、科技部发布《关于提\n",
+       "高科技型中小企业研究开发费用税前加计扣除比例的通知》。|通知称,为进一步激励中小企业加大研发投\n",
+       "入,支持科技创新,就提高科技型中小企业研究开发费用(以下简称研发费用)税前加计扣除比例有关问题发\n",
+       "布通知。|通知明确,科技型中小企业开展研发活动中实际发生的研发费用,未形成无形资产计入当期损益的\n",
+       ",在按规定据实扣除的基础上,在2017年1月1日至2019年12月31日期间,再按照实际发生额的75%在税前加计\n",
+       "扣除;形成无形资产的,在上述期间按照无形资产成本的175%在税前摊销。|科技型中小企业享受研发费用税\n",
+       "前加计扣除政策的其他政策口径按照《财政部国家税务总局科技部关于完善研究开发费用税前加计扣除政\n",
+       "策的通知》(财税〔2015〕119号)规定执行。|科技型中小企业条件和管理办法由科技部、财政部和国家税\n",
+       "务总局另行发布。科技、财政和税务部门应建立信息共享机制,及时共享科技型中小企业的相关信息,加强\n",
+       "协调配合,保障优惠政策落实到位。|上一篇文章:关于2016年度企业研究开发费用税前加计扣除政策企业所\n",
+       "得税纳税申报问题的公告 下一篇文章:关于提高科技型中小企业研究开发费用税前加计扣除比例的通知\n",
+       "
\n" + ], + "text/plain": [ + "原文: 【东奥会计在线——中级会计职称频道推荐】根据《关于提高科技型中小企业研究开发费用税前加计\n", + "扣除比例的通知》的规定,研发费加计扣除比例提高到75%。|财政部、国家税务总局、科技部发布《关于提\n", + "高科技型中小企业研究开发费用税前加计扣除比例的通知》。|通知称,为进一步激励中小企业加大研发投\n", + "入,支持科技创新,就提高科技型中小企业研究开发费用(以下简称研发费用)税前加计扣除比例有关问题发\n", + "布通知。|通知明确,科技型中小企业开展研发活动中实际发生的研发费用,未形成无形资产计入当期损益的\n", + ",在按规定据实扣除的基础上,在2017年1月1日至2019年12月31日期间,再按照实际发生额的75%在税前加计\n", + "扣除;形成无形资产的,在上述期间按照无形资产成本的175%在税前摊销。|科技型中小企业享受研发费用税\n", + "前加计扣除政策的其他政策口径按照《财政部国家税务总局科技部关于完善研究开发费用税前加计扣除政\n", + "策的通知》(财税〔2015〕119号)规定执行。|科技型中小企业条件和管理办法由科技部、财政部和国家税\n", + "务总局另行发布。科技、财政和税务部门应建立信息共享机制,及时共享科技型中小企业的相关信息,加强\n", + "协调配合,保障优惠政策落实到位。|上一篇文章:关于2016年度企业研究开发费用税前加计扣除政策企业所\n", + "得税纳税申报问题的公告 下一篇文章:关于提高科技型中小企业研究开发费用税前加计扣除比例的通知\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
问题: 研发费用加计扣除比例 答案: 75% 正确答案: ['75%']\n",
+       "
\n" + ], + "text/plain": [ + "问题: 研发费用加计扣除比例 答案: 75% 正确答案: ['75%']\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+      ],
+      "text/plain": []
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "
{\n",
+       "    'exact#squad': 65.70218772053634,\n",
+       "    'f1#squad': 80.33295482054824,\n",
+       "    'total#squad': 1417,\n",
+       "    'HasAns_exact#squad': 65.70218772053634,\n",
+       "    'HasAns_f1#squad': 80.33295482054824,\n",
+       "    'HasAns_total#squad': 1417\n",
+       "}\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[32m'exact#squad'\u001b[0m: \u001b[1;36m65.70218772053634\u001b[0m,\n", + " \u001b[32m'f1#squad'\u001b[0m: \u001b[1;36m80.33295482054824\u001b[0m,\n", + " \u001b[32m'total#squad'\u001b[0m: \u001b[1;36m1417\u001b[0m,\n", + " \u001b[32m'HasAns_exact#squad'\u001b[0m: \u001b[1;36m65.70218772053634\u001b[0m,\n", + " \u001b[32m'HasAns_f1#squad'\u001b[0m: \u001b[1;36m80.33295482054824\u001b[0m,\n", + " \u001b[32m'HasAns_total#squad'\u001b[0m: \u001b[1;36m1417\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from fastNLP import Evaluator\n", + "evaluator = Evaluator(\n", + " model=model,\n", + " dataloaders=val_dataloader,\n", + " device=1,\n", + " metrics={\n", + " \"squad\": SquadEvaluateMetric(\n", + " val_dataloader.dataset.data,\n", + " val_dataloader.dataset.new_data,\n", + " testing=True,\n", + " ),\n", + " },\n", + ")\n", + "result = evaluator.run()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.7.13 ('fnlp-paddle')", + "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" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "31f2d9d3efc23c441973d7c4273acfea8b132b6a578f002629b6b44b8f65e720" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/tutorials/figures/E1-fig-glue-benchmark.png b/docs/source/tutorials/figures/E1-fig-glue-benchmark.png new file mode 100644 index 0000000000000000000000000000000000000000..515db700127d0d2f4dc7b139a29bf1749419f2c3 GIT binary patch literal 158817 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 LYAU>iJPG?JTa{WH literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/E2-fig-p-tuning-v2-model.png b/docs/source/tutorials/figures/E2-fig-p-tuning-v2-model.png new file mode 100644 index 0000000000000000000000000000000000000000..b5a9c1b8924fb5ee5afe07fe3956ef28c428a054 GIT binary patch literal 50517 zcmc$`g;yJ0_dnW};uhSYcyTE15Zoyc+$m5TihC*UR$Kzb-Q8V^w79!_aOW5Lyz8#- ze{fkVFd34Qb7uC;{>a`5RaTTjMIuCc^X3hzjI_AQn>R4UZ{EB$M}ULwsYs~RgZ_Ez zs3HY?Q$9w#4}J39TvS2y&6}!daoidyhSsAoFzB@p6Qh-F(cM zXWV`D#$E6|TmS%wKo0#C60a=tg7x1v0=c5!JJA2P9r*wEc6#R9yrxiuSvL`^B8gbh z)FowE#~6SRfHYO>4{m}SR$4N9IhF-0b|L1!IsXcQ4Zhp|wZFBiAII-@j_jr*IhM-gqAm>N$2;s2*}9s`dY=&ruH&2GJ``yvHEl+C$}>L zpNM&-_5@18#@OYYGC|u1yYm^YD~OSjls@fJ(WG3_;SB71Hzq?^>zXM-@2j*uex9qOwK18nQo(U{s@grP zwErXvvuaE2CH&XjEcCxsO%so^y> zbGYl8p--+Fr_EV%di3v&s{vqFQ0h!N$IUVAH??1~Az155m99r~eyBuTYb~ek@%e;R zX_)Wf;EbmVKQ|thx5T8R(2Z8vEHyfCft@aBU!3*e3|0j_uca%jOQKERzkff+*jETW z{B(45ADNgE^yv(|9d96Q+DYf0?~DG?FF^Y{ywMV)rb;fD6`=iH3w>};ZJje!rGt^_~$)Kv2tcu~kzJNvTTVrT(i}mrGw7`f%{KkQ- zbzne-hhpI$Q^cVvqaWIjL>0L2a^eFRmz^Cj-aX`-Krki*N<_73ULMD`NPu2Wl}Db9 zNZC}U$mG0t-sD`?-)mPMAL9FFH$F`n0j*^-l_}a^!eWvLS;XOG4@Y+TNG7xri8b~D zN;8Il-@Kd>CPu?r-N-fDeZu@7+0_pz(7J$5Ud1uy%zouQ565NkDYu!f^bHD2d?z5BPFpWkMxr;aDo?#C$N)Fxesr0NU;nWeAy+e%*+Ag5c|w%n>pCVIZ>pv>&DwDYDZ_oO;!;E9Rh~l^4|cbjdxmE$;3TBn7CN%i()L%)CnB_SmA`| z$>98&&fl&Q#Vyo^k2<)60EfpifW`Pr0xHB3mJ_F|nz+cch>7D3+5%|eN z9ZKzjUX{8@VXaI+@gs7&y@VF3FMUzwr{;@9zG|tydLQL8hu$gAbKn9KrkE`hNKj*v^RnS$Z(S5!RR=?6-czq&EB6fKY_<{m$L)NmqgH0*L$kT=SvE zW!gEFWcbCL?iHBTd%>P7(a(keRz-t91EZE6nK4;xTK2(J|78|I{kKE@8V_>u0Wg>nb~o?)crIu2 z)qxq#ocsEUlvr<;T*uX$>M#<-8SSd=%RuaV?O52~8Et=7HqZ>XDs<4lVz>PLyZJQ} z?Oc7d*tU(eaX6_+bL0`FyKEtfFifZ~t{^dNK6+K>8lgF@9XL(U250rX6W%^rlAN;o znFnd?ryNUhL961?!$qCui2s&F&YInF{+uH#DVU`DS_ci2D{rH*yWDoV0ls-y*i755 zZ&QXad?Mw)wMdsiY^@Sm449)j9!^?}HMqyd^*`)=M1{LKIQoNHUwrDHJS=y7NjI0Y z-JR!>$2(Vji$k?HK3!$vuo_UoQW`~+XIPclQxpF zH587VhIw0#GX)c5_<>AeK0IP`wzsJF4tgl1vDTk*Uc>Gr#9UIp)vbzG^Jzf%ncNKC z#g^X91Z>7x~kREWi*=Jf)JXod+D?*pchzZ63M=Jgom-EN7gF;}Bq2t!SMGBXqZUOQ1r!r35wU1_ZzpKxMn?lfke+WaHd6~i1a#A{%z=Yoh{cwvZ~Q5*0sQ0@v+5K z-wibE2{Rv&i8@F)N(Q~yXE!CdwQwP+AzFx&d7Zs&e>mZHc&r*A#d@I)7$i_mO$)J) zgy)FW#^#lPLpIl?T|~K;r(*WOvOuFYw~#HbGw3T0Z>jx5!`RzHsu~kxXT57S`0^%v z_G|31w8*5qyQinge6{HYk6new*_x=s5^tT~_)pjn)GZsSI?b2$SWDTx;m=MY;bk5n zd0{W9Q-=86b+A%M>jp?(A?5E@goOlCslSs2V9RAsGm=31z=cT{Kb1K2WbTls7s|8svUIi zI2#DU&20i!^ouB*1|OeuL7i4e_F7pD6z_$You%}>Thzp!g^uD#ckH7ya>`LxGUO4= zq);j$_I|J zgk$viwi05891I2I#B=5}hss7MrydYo#$=DPYVJvA|+b(v-UBWP>k zEx4?wWI>ni`zP2&1LIofEb|lGZG5zybkki-WF#yhk$N`;+)dxrm#;@c1I=51>~VSF zqeFAMbpS75P8J1C+K*k8gKFFv7ud|E{x#O@fWWlo1VRza1JUXA;Kd_;J< zCMu@|w;(U~zeSd5t5`^3oCLwF26&L*CpCNj)Z$SDz!b zcqyU`xHZwpwdlRl`wv7x{`On-2)sxB3mF1hW@eb^y@IZt*$gPIdQ6DHBr<#CAAob# zEUl#ERQedZLa&ki8?ez0S9wzu*tthV98<_T5~FGQA&oq0;4edMf>N>bb7@ z_@!h&-(46n$=cg?lFKN*aYg;&c6B#A-zuxQ%PF$*kb*@k1lQMh?y~bMx&G3L98mqp zjVsd5q_xjSZQ*&?+u}-a<_3k@9e5C>Nj}mV1rty?7hM_^f0Wr{Y&bx7^)sfRar|ew z`^2A*%G9|S=|bKMk0wd6vE&NW3B`zNDZ|1OkLX8i*N78e<iHRE4h8H!zNr#wn z`yK45i9!;aeu+p&v94T#e2;ZGS96Pc>JbKH51QHM6nqX;T>MXIxZPb~K>f89Fq=>i zbIQMQzU60mz-vK4-uqeYDk(|$J4&ZIMjTr8JOh5x5d`)7j7LEQ#?r84;0k!{v4<}Qq{)V(JNd-K!F zOSLsj`VS(*-PDyW!WLDpItyuOMKUtK`_5XdVgM1K;4wy0S=$n&#BGr{vlu+}^Q|eh z#+(hyZm@+39NkikW4|~XSp{Nn|4*u&^+0Lq-$}6bM?1U^j&vyz!npYvNehH2LOESM z$PM%~w$)zX{We7D-z+SgQG2v+f$cNo*{WmNtcD9EqHQV0bIoDyb zwUUF39f)c-tRRj8^HV;PT)33NOn%-CKXb!IYf{$oILIt;Wt`oB8MVXLp?SR0ZhZJR zqe`FZLuEt7J8=82wiZE6@>16=CJ%w9@p=ozrffVybqj5jd-R=5`jQ#aaT$X3cL3$I@+ccnYskp@GGaMAEL{!@55u@J54V zIORyMfUI|?=JQqU=Q9oY$}fGY{ys2Txk&YPuVAE+p0mw1EH>?o`*xWdS!N?@*>BLt zCh|dYAvo$tBepZ-9F(<<|vX3*s{ZbsiEhRWM(!yN8aXq>mdpNlrEE|E(wT% zQ&U%`VKivhEqy2dQ%&`%VXF|pQm4t3Ga3gOfcoDejEUO9y1$SEnJUnR+E4$$negK~wrCx?ut3?NOL!&a9c^}R zE$YNQf4xAxc!`V5|8TvEXBtxW)*NmT6Pg{&RbVB%kc>2&T}P3g@w8=Fzx(FAc@)8- zG-xkC%%T5Ubp|9fdYGljG!y%DvgSi4UuFI91>*fUC&AEA@w2!cxWe^E4OW#)p3m*V^{$>W*6`WEm0*06R(Frn+82?TidW( z_!J(nkUIlkxjEuo80LdcP%0o(V&r}HU{Az*gj`In30TDn?@pfO;#0MMA6XnN=4>1P>v?OFE_ z7!ON=dujxZd?-9H9|^5z^jF$;E*BUtU36SP@3$$#GO6({WMqqV?lf89?gGkNX7{nN zRs{1&O1G()N|dUVCw+TRyMy_W`o6gOH~}2a*=~#9BAS-*WT~Aw;lnDJT*Uzodg&0xIMpr8LuEY@*jjx&|XEp5h8r&qKf=912ag!1OD2#GK*)4 z(zWN=Ojn!oXI;9>y~Nbf^1YHbz`MjNEC2UJfNRG}|KBnFuXd2P^R2dmSrD~*t)zxS z&aBHy+(Rr6lY=vT^;H|~L{hrNc9*OLW1E|nvZwBp>&Ut>gjDY7;tJ7~=Wo=R+V0qX zYz~?Sy)|&l@U4)tV)<`I=2TeA2En)Odt##SBgr zaR)jZSFFW-iDAu))rA`jKZ^9%qj3G|@AOG6))TLMa?D?Atdeysqsv%~(&wJ8sxz3+ z-?pkscJ<9x)0_W~HVB!Qc$DQl)YZ?{1qcc&oq0t0r3ZLla_2}&avTMK?#)q!iu&zA5N z&&RjJCT_D(yYdF8`p@f?3Bf*8GoRD#0czjzt*bHu9t_#*hP*J8%EoYoRoSoFT2ns; zp9I^*Fx#-z=TD`8g8vDi}%-z>v{V&87$C18bdcg_k(U#XDxp!_CqufEzJ-`53LrDQ(BVA39%|eUV_}zS@od+XsYlbQR z9Njee=|^N?c~RShG?>jS9h@(ei19h{G7%?!vVxf5v*P42%U=qlB#g_iXZh56 zN^&N2zv3x=H|u7uO-}jI-3#l+SSW1ilSW;1y3I)&M3GzOhWL3u15mYYDt`k)@(+)# z(2Iyo-JhG@(E5T$W87upcXnk-K3c)wlk$!jW3%@jA+8&{--=MC&Y+HWGFw4rHl7)I+Ww%JDu>{p z@o(12NSQuLCJInolj$FzRW+yerC>R8+4B2tZ241SAPc7vy+U)uQ3Kuwr@AOu$(Qb> zH_jx!0*9XNb=gxcQ@!6eE|p?Wl=;Q-S8iGa>lgFXKV@<7la2?Li|fCN5GSm^ExWFA zKOs0}F>Q9XpVfapSj_ocBB^+9GjRIFA$NCL@H+Rk#lfNJ@NvjFGPgF0UVgm z1Bn_M6r9_z9lHi%UieC~H5fJe&)5<(+~p*2Mk5^hAUpU(#?>I*Jo>~wULM_zygw@n zeoe9^YN=|Eg7pL5{U?01YeSy}51xCpR)3eoMxBvip>W!9H&Nm0d`kchh7a;RwnX;I zf4XX0EdeRCsMUlIE-<5>_Tzix*5c7Q@V;C((K;X-n0Cu#7(P$x zXqz>5)3?U%I38`dhr$9X3W%n>VQ62g5;C4GakpONAfn$VE8G!UG1SN)XGZ zF?{=y7ko7Q^@8&;Ep%+G)3{YF=x0kbSS(88oTpdj<}@wP$a9+@05=#4ptS#nubaCw z^~u?K559m~C6A&!%11?=cdM}s*}KOiH{zP6uBN9SCpJ>Dv!(x(VBp7xpeIJwBdDO< zA>z-nVA5IZlHi7;I%f7#37a5>ih@JS4sUXvMm`2O+4a$EQ5fk0DCW~(Ok9l{=+>h` zmJ6+RO}>78yJOyFE?=#Z9u(M4S*1O`=u9&dXOu3r&|QV!q#e9=%W)KXmSF2*qmVS^ z<~|z(2GG#(sYn%2%>EiRXWB_=083FCg)FneD=D6{pD6j0&g-m-etX#0#5G1y8F^4& zpPTyHq0wL z>rEZQW4G{R2aC^~G$kB=wITKGUumT;?y!|dxqs3;7w1vWM;Dj3e3uC8tTA`E z7J9N!XXS8rZfX%${ePSZ5Xh@zYimoo;^*|hCpZ-R@0FFT`yfzjKuhzcD%tNfo21>* zwBUN1MOjrw=qnC3i5(g)M(7~Wo9VnwwwPwrV%uw$l;!sNk-m(fUtG^_2>SoTJ7CE>h zL||2KdFL%;&@NW^$pxxuk<}(VJ)~U6TEvvahZdbmtNLb9YXQBy)VGBkojNpH3>t@@ zd6@3W>i!xOr#C8K=mfMPX}x6c9JfZyvD-LnCfyXTj`yI>fE#(a33ubz>tD7({g@0~X#+6Fy z3P#3bmIhbW`$ zHb)*yGkjW!Q;9pifo7^t)p-8C#Au1*?d%~2Kv-htk(SvcNY{P@X;#nXk zbzTB>%Bped)zz;MvJ#lvonV%#6{jVMM`ABDlb~o|OtiC1T`t!ws>vU+-e!q$6Q2oK z7h-jz(ba;DmAD(?xeAn1^{=P2(&<=zQOID{H%3)*fag7)d5;;Rjzr#XB$CFmS#K8; zd`fOzx0vHi2e~p1TiBTIRIL*&sR5Mk#}v3D$#Sl4p$7$EA9@=3Z*`a;+<-a8yl)Md z)BW@bd6?71gqs46lK-^5TXgMcQo&w_JmJz@j3K*5lIAAb-cT9Pug!NWHO2RO<9p2x z-y;uJ#Cu^-R!*Gu{$$^t|7OAQM_6H@M>keLcPSC`RYG(yxI~tfrd(H={PpWsFJxBV zQ^D(pJOa7%&VKans&?pKoy{}F`X}0hTylu@qz>fZz&1qhf&;b)DF}st0xq$2Yf4=P zZ+xBAYKF0D2LoNxd?cBC6zcDAUot?){q)qe{nP<5OaK566k(NC2OtZcVvzX&yx6Sd zp%e}de<2(O+}sVnDTQRaSheuvv$dZ|J`2TgbOX?YNoTv#N`S|#D`IT?OVc?PFyW;P z6|^bOArOq0xo-m7KC)q^$V@+yA=i<`l(_F4(69S&@s~l+^g@3&ir8DdtYQWKcx#s zZW_-<@O|;|txol!Ms&bo)I?1VeR*_6^B|S)(&)P)DxPr88HsrzPo#3~OnSfP!8}=Kd)k8bi~G#b9b?);&3i)z#HCp*FE*ZAMT(NlQUKN}|Ud0N6Np zo3YWa8Bc&N?LXTC=X5wg_~$mrg~TFW7Quq&(E|mV4ob!@v=PgHSQh^C!DBqS{3p#b z-6dP;o?q2`^}o~s989V&4YW#`*e|X)&;Z#8aN8aA`T*6)b>E(Tv*`&!HTGSH!nJaq zNY^2=1L1T4&@v2KCyZFW6f*_*8ZFB834`P$C+ zDB~)|;t#(7rNReGO*L~*-?hb9-UKZuq_1dMPG3K> z^Lg$fSeh&N>Tp)>w49!e?K6aZrYC}cJy%H$6mMFY#=NhZ`03LpY+)0@N)g>g`}H4} zbaKJyWa^I*SDi^+wjp`1-u4~T4A(+`eE4~GRdV?0)@S2EZl8SyX7#0>W9QRRhPhYf z>)n}eyci8?75{sb+h-2V`oD}v$Cn+`1aOoU7Jh_ioB9=V^l>Ur8vxS*EP9$y-{p2H zW0~sv@|RE>@43Y ztOr-&ksqMc&`?HmL<3?hQtzG}k2O7W-aahNrTM+~u!<{{*fr0Op05OEj+{3?6{z7> z8e6%ac=h9Jigk|#HnnVR5@?zy-TURVJ08#FwzjuJm&+jS3Pson02T17IuS4xqh2EM z^=l!IqHy+Wp@oB4x%O3(tQsOT8eYv>9vrA4LY^Dc>~c&W2^Hm_d$?IxSRlTc5t9k8 zi$o|Q&lH@Rx(@dNzP@K;#0}16CDZF{t!n~%R)o6vzhM9y`EKtxHIP+!Ux)j@L;v6H zTr{^9bm$!Dp?rpk6b3z-O*38ny+21vW68I@$>-2uK@K-Jh|k{scPwsEsH_q&r3|g# z$YopW4n&^7C-3FOS5B|TCmc1-#o?ahzpe?6Y5WuznQLgeL7vX3NNsz_*ek1Of#R^X**m=yp#LBM{V7IU*LEo}4;GC+(j%iZB4;U! z^L6>qJ?r)6xZJvmqbF-M+LwmdY_&Hdh^w_?`k^d1xQeDl&8uM(<>RQ*z<^bEb}W+| zRy!P-m9SKOdwLr+o(`76A^Be`3}#Q??K6Q|5AMb;&h&o28&|OkrLOkU@QGeCNs<8G zs?B+6R^#qd80W(6lV(b{G5Pnv$j)SCfj@P592qgPP_Hf@2Wb?e1`i~+@2QOd^oBp3FOjF;ABkFRgGMFSJWxC%4@0QBqOp{ArC?w`5o z0Di7vRJ;1I`a@|RvK)*fy1Z{Teq6M+&y8+?z~@zE%rWKE8JdurOLe*T7e*?II5xi# zjxXUgP&}d4LuXE`j|FzHzv5#XJgF&w@76cz9}gNRterhpP}%HRJ6C4ga?-_ zo7kzP?m{~Hh1)GpLlJz2aZS=e19ccg#wq8w8J^1AnumJTvaH{;cfW3*XSvRb7DmJqi4Rs}bU?VZ1dX^{&zI(&V+w8sa z#t^i#jOR~W;wUlt+~`5SD$br~NHq!gRgosxE17b>$01?>Ly%uJ4Isj2CxUr97EFIN zLxG*~6a)h)Sz*B^$Ybiq_oM=ddSV=R0uSu%@>Pp*Gt$#o@wj6>BKvs{EkT{mGlamhaY6a$y_rJniq2dJjnm(GKuhif&|F9iDyjg0dnPegA$g)8D7hc}^8 zeN3Fa7QMuEYB0m9xoh%|055kO^USXd3i9{Ut_t<0pP2fy#`~GWj~OL>wBO+hmBuET z+wnIJZ)=ppJjeqH&oiE~Mf^!k5MQFAXFuqgEO4vD)zA;jLwaqwYi6@5yxQHLs6q85 z^cN1?EWxyXi$S%I#``3;5zW@$6y8CjYNB)r;50Oj_^4zEy>6~$hd|^kKGnCRB2Z_C z42wROH>wCw?p398yAgI(polnRnTxoo|yj&OpGeVO^~)V9JOnK&<(2Lf)z% zV0lQ&+B#=TG7+#C%yP&}uBDNN^9^n`uzM@z2Op3AV7!aFgnlc)dO_-MQ8&)!7YUqZ zMk8~tTENG)RX6K$mW{FCo@K&-BzbG!86z*t@0^8($_z{3l%O^N&eC1oW9A@Ig>D0-%?Fpf}Fob%Mia zs&)^V$(WPwTzlv;1Bv^g1)2Hqr?&nQ)@~ebIScO|ZX^1ZD^us2w)7UK(4g z(g4+g-8CYgC-*?hT0^SMNe7*AGkN=IPv}@J%;d@ z_82_$>iStUbKX7VW{<0oyW5olY|yyoBA>HSRSXA%)=+`NQD4a^xU>f2NHNv+R08l- zE3>08RJPIS%5#zaZkU&i=OJ-1NFseIz3~k_^R`U<_FWHZnsIt-7^cUVB6*DrRDUZJ z7)YphEC;k$=N~OK**1}YZ1+re^%LBaGz|q;Zh7zccmpMQ`sF2zssUX>23OfIs-Hhl zN#T=yP|INH$UlBu3E92Fs&-5f9zozJkG3d0Z=qn)fg}%-4i=ds4F%Sdx;3>EX;lHq z(jEq%{w1T)kp27*P@vo3g0sKEDE!7HTlp?0@ODa|$Z1rRnXFK@ zOFx0g!5y$CUDPO${F&Y;E~%Pfv_hbw_()DQ<`)1(E%B1)UPK%huzNFTzB|z1;oLz!JFPS6B!{s51W86u~~x=y>o39Ai3{kreUO zJ!t)MI)r#0U1;5^s)M(dA4^Ysrk#b&et~DnD)vY=5bbR|tHF}6N3Qh);lMGM{QtCl zp&X3+80VK9roSsCIULXMw>PKSranoT-bN$)UKmMoUr=E|f*6>-*gtGxfXzBwgz9xS zKyHgxk5;Q+FNUJncKm{GFo=G!4q3YYa%sqxrQMsbv}o0zu@SAOIr`AnNCRAL-d|zz6?x-t>4bhC4PHH z7yI-VxY7?Iw1q@>BSJDfh({-f7IvEP?ws>ab^>+s95$9peNCX)D#mPF`P=7acSkdN zxBCD?kR?}jy*QhOO24rSviYe0qISK<9|A^=Q4+08~1TU*J>lp9)i&SY+`EZvKw z*S-5@BZYg6ipH+}XVOCY^&z`gpEFcTI*tZ3pj?aPNIN3MN2DS3hy|@LsR^~+8n)j# zKLue;%%R3)h>DSHrtzf3TO4&XC>dNHO{k=62M!b6M4XrtD-DT{Y2ESu0>Zz1PNtD8 zZh<`eO(s4x+)5oi(7liK%g95FVlC4k3!nyX)O|cgYX*rTiB_iVO<=)5^W$;z5?q0h z0@3%RB*=PbK|#T7N6A0*a*&mkB|=DflAD*$9VD}h>hrz23+(Rj?I0im|Bpoa zlz^`P$(KwHTP32e9&=k_YJ<5MF}Zh+X|G&LB9n6uxoNp9Z@2MUC=*YWMp+MjLN zfvSbMmAqL?Z%8U3AG>T`3!h%)IyAIID1!NioY7?Emg|10vAdSwHK$Mtl~|^a4Nt=7 z;61|MxqD&|afzfBO5G3NX;xoo+#E$^-+Ed{TLr&b5!B-S>%=NK?)H7x{pw6;*a_jA zkz-j>I|~KtShr-@OBd){zEwyV2I&7ajQm96ouB1OfYP*Uk7fr#F+Ca!l%`Xp{BxR2&6DkkzuV>k;v zO@UT}FSj<o7d(ar~-SHr<7#9xlu5jvmj$d-J#O-yd)r&uokiPF)x#Bw?TSo@+FSkTqhT zGI{1gAG(34$!M(9FFK&DI9HC+v zZJktFTqAG>aw2_Ec$klr(_8E=A?mPQ$oXwEdPyGkKb%$s#9iW%NchYP!~9&4noC=J zf}mZG1~J~i-RYJ1*{GAHeNQPguN`2aB&4RGOl9@3tE`fDZzke!Ph(>7)gFPgtszL% z3|f))tb-EgCS&@FDqDR~e=G(4c`MXqluUx<&-=vACeu@*+aU7Lskis(0%q&j2T}AO z6;7>OQ5|#m-Sm?%w)z9BxS$R8Bmc*Y#)J;RewD*j``dUj3?5TyriJKw@!7X;Cp^4^ z3SkdpXoNHihhts{R#=pq91IO*d8X0ZII#kSo09GYOPA-mgDN4 z69cpw>&E;;qiL4X^pKReo^MPt$>B&D_rX_SXAwofv_r5Ju5;$SSBy~M4muB2LP}7| zWghFqt)%Pl;!UUNVc$st1ymBlxDGI^~AOrs6K6*NYzcGRXYZZL@8(n7PLf<$uW zd}jixr`9`?CtIrinyduhI?-tBW9{BjS<~!y8b2I0%BzM} zjja|~tS!)7Bzo}A>!e4@D-QP0k1K7#qcFP?Axpme92 z_kh` zTi}PBaX!SHLWRoy3HyQM_!s@XSW=wOl%11oH=-5q5S`X{v;{Vu`IaSi4SwS$<(jF+qrAmGxjBl^myFu7Eo|w0sWmF}6Z&;SM4*+o zIiVt#s0XcsE%$r9bH@#~L#(tueNX}LDy1bhjrJKDuX3@944_DMuf*p&=q77JlF zK)!}|7Oz$=bYtS+THIB9BH5JvALTmI)@W8NF%f{D`df4qR^K<~5;~wZc1u)8$t702*E(~ta>2(C)6-0IK8Imx%K zjJ=+>N41`eue{h@kw8VxcZT>om@$BZTCe&{ zH`3=~Sqe&~ZX3vXd9_kE2>+>gJRuFjroz_~404kNN=f}850YjT zBee)WeF@=^gw~u(4~ux!lC+K-8`)qjN*ADa+qZZxVFE*JUdsifQ9n|Hw4u80LcI;c zYc)5w)5ZICw+D8S4ophg{tu!LO%k8zvHXRIS}<{qxBhTMtX}>!wRrl>z^hYSrYj4&ntw5~8tgOp(shbr=d^%qZA|(Tj#oDWRP;9LrSre~g`~y(tLF))flU zlV9CWH{EE1ZgPnul3hs$+NPAJss9NuoK#B1*toco(>{80p&xyhC}0sc0Obky(oQBG zOx@dyUg5&OEdSIoSn!OIm43<;LO^nVhm0AmO>>5MZ3OByN!}~SPm_aBDHokM6VP@u z*&4=%2kGk3d&Z zAron#dBlPs(Xu%L+D#WW{e7FzQ;;WbdurfQWBy!)?12eEdAEm-p0}s;)z(0IlKQGo-ebqpB&6;k6|QPc1&pMREUA1+-6#Q!9#}$=|B*N%nVPG0pF)Ius3~ zwzBee!Ca4X6UBj+yR6L>x32~*G{yIFA;`r;(WPZK&~`e@Zk%UUp5H!src?Ufj5&1j zsT?w`vDIiQypxwW4C>OVua3%%)Ia@M8cR+_rYo7vBv)e?Y6JAv|Lwhk_H}tZ95+lb zeBk0zC-mpdX-rDO!)4KDjKaDR&-025zOJ+SPl>ZIZf$ccP|V2H070HT*xA|hGadB|~Qc~tN70Hg0vFPIG*Def&h}ECW z&{9edP(lfH=Z9-ZoP$riHF^b_;!=1=M+b))(F;k|hq{v=KYrx0E$+EazxHsv>g|62 z!W#7X&xX&@GSx+S#XtAISMTi2lv>>)u4e~KufyYg3Y$sLrL2~{eI89yIk)(qtb{3}bkds2=eOnt8rJP<@}u$Oh9O_nxrGHQJtJ`iu4 zl4D;(!z}2O3I3aMd?oYi$Fv@&f=_+0_m6vbFENnJl zOQf7*11Pjq`|enP-*6*7fm^fu>(2@f6_|3j)&t9#pKrEEp3umA90)U7IKcb&K;i>SBg^lm!R^8!<*Av>WVOm!2g!P;cAYn?#GS(2M?dp9(4nGG^Z8x1 zy8=i3z`#c24ZHmfV75%~^X%pv{s8Mqo_Xc&rYi(2=zexG&9gkgGwF}7fvQ&YYW)CI z7;p*;zb2cvJ?7W(CX{lz_DCvr=R~U#_3i9*Wrgl>+ZW2g7nK|L&JDTQZ}mzdtH?b4 zOMM7MMQMDGkNO<-UXGHfBIz1Eg35&~kJ$mMmBlHBGO8Gcg@rNwM2f2|L53SxqZNdf zs`zU+v=N!oHl2E?|4y{D!V+Wedc!Y>dyBmQn=UH;w<^~lxSR)1O%z{mK~&QTDc$(D zrop(I73zze%`ezTOpX0J24d@D+jCXIM0lwEN<1VUSt6E4e9WZoM2E8^ou(GDViwE! zOp;2!){5B9yal~DD$Wlc(aQ;G)_N5=n;l?MQV_4-4jao5TwIyUyD;D42I zfTpP7s#ZaUFKnX3LLO`g$GKWFD7)2=tLITSZe7wf%gVK@(Lw1=Kk!=(--QU0;IT!N zfYBbYaEIKfF6qBnQa-8MH_y(03BBrsNdir|=UsgwP}mT*)xNr}B6(5Sj6a*~0{F#N z)EiM-$s#*NmeXz@HX;WFHJBA#F=x=RQ_GCg6{C6$9?*LaAABWDgj89vy}k#$XFAU~ zUaH*ZWAj=8YeQ{Uk&3`kQFz=bkojTWdC>-PQvg_NJ;o`Nj8WW+kT$ zzAFf(5qY4r*Kp#xPJ!uq$4I(}c>i-h*~1lC;C_xqcOCrs&iJT>kLv}KOEMA<59Yne zLE69>;>(f-1MA$RpYZOZnX3b<8S`kT&3GP>uxIJJ7xxu1o+mQKvz9>bU6-G-cCI0^ zsHqd*kC$?>3JsG+`-Ud7#8UUd`QYu}eSyorlRp z(jAQ)Xim^zwLLNTdohDMacLIzbQ0k~|HiyQ$d5A=KBHkKAjk52ZJ5O02~Ps5Ff)g( zCaZSJO6S3K(Ae&*mo&VfFYgM5d)k)tDU@P=9P>H$MA1t8p<&X+l*KgMlr01u!Vvrb0vj zyNa|bY;`{bZ4cv~@0oLhzxDb)m`87Bs=UAk8xdJ^nVIj!v z-rVO_o@R5()!QmZk3Xxdo~i)Fk<=)r;IQL(hOkUv~ubbk1s(Zp1kfgURKjd*WAGb|MkYJ z0sNkPNk2-#%weiB-k-CN$?}b^bxa_RQ@^F}@-$OV(SE;WgLQ%BpEK;ZrPt_Pxxt?x z_Y-bg-0np!2@I=-2Hh3-TsuNe#S)P|4YRhaq&^2eUL9XBgr17BRpqB^nx_IB?mjGE z{ma<7^BXdepD?>eQ*7Lg$@^SnI(9dL)o_APuS6pmUAH42dtv zX}%D;WD$f>wanqODDZ1QNB4BBbRDaao&%TIPv!yB%3Xm)t+Ayf8DkcZeP5*+ zB^mq3=}W(EXiP4m2?!!@!pt|<(BZ`i180gn<`2acy#SxyW_-e`d|2D3;S>I;mPN%) z0{o#5{72?TeCCb+vbFh$;P{`qIFnS(j&gX&^;?V@Tw`&sK=BPEPH&8l!w zdfZZOkZ&tsIE&B`hl}ADEzH9>zaaym{o#}v!6)isa`ad4KWz+I{`et+o9Ag=`=zDg zbBlGDzn*C&2~K9aad>zhQ#5y?HqV7J(t@nSc7o8a^6lg9$)HzuuZL%%=0Q&oqn4>< z2BzmmjKdHIW$w8vIGwqYx7pQsw$sk}mD!z>8#zRyC@wS*ik_u=c;4txB%JZi=}Y*>;wK%-D9};ktLd?i z50b=$lu%wk_nqptRTolMT=#gha^%2WFUQj3W%L|8mx+sjwo2aGT7g#0kD$&Km7_bb z(w9y}Sd&H*7|rF z^TKL{eVb$2yB+<2>(`7k84FGCm*%fPAOFN;SwLT^0PVYw(^IP3-dFA;Ymr`nME!K| z4yESo{p|jnY|wIOfJ=eMN;~<*9j9rbQPNu9NqSt!cIZ-zM>V1Pp27YoViC%zxB~y$ zAG~owF_sApJ}Q)MdBI@CSbgEX)nut`*50xcEqP+<8dIlhRWK79u8)VbOuMlA=G2xo z4`PGhQqXoJ=P{p9YCuVeVxQnE5k%hEXqK-5pM!YHu+~Kv`~A5OeiOk*!MYy1 ziRyhmTZ(yt_E;O;%< zH)k>MOVN~mMW(v*3qRWm+r+su_PZtJdkTAYr*iBPp}{yi{Yr!_rzrH>@D{IL!@R^8 zqlwgV)usuOd|a*0Fm5l5jJf@m)p|wrB31wbzus>1#{|whT@mIP9^RXn8LpQxyZx1t zF!6Q=(Ozt@(`vu<27iQ`>&`n)#CSki`iv6Y_jke9XmllTO3LJEAHJhokkF9otj|uL zxIbEq@YW|OaCqs(%j;0DQ0okmrgV9fW(T*cScuQ{scSg^cDyq}lL&Dr{fh^dDzV{+dU=`Hz$?F;*=>$|v^i|@9f%R<|n$sv|GLr$*-r$9uhlpb!LiA^jUvN&s?3(D z>bYOJA}VZj^o0D7E|08`lHHpH^R_^apS_bP=yq5(mzNxoknp}FMVAxcpjP(t*5>?9 zaFKrAd~rr%ygW<9Z0Do>5QNJ-a}{&6&-B+Jn#C-S1NJ0`)Z^?fKBR@-{|OgA< zY*6)`OUn9L)Yb$8+v$(btQR9G3)=6R)(CLZN_h%&{gCl3ei?;9zm$&FUN?SfQha8* z39&f0SirD(Wg_aOUliI^=}1mgZk4A9;c~guSe+{E6rWR4uZHWOJmYN{Ky-sq7}zu* zyk8yJxo{mT?am)=p<))x9Nu+(zziIGHt)#xQe+3wpO76InR*}+r>skT(QoV<((jG(;kXh~GnMvaT~Na2?P zD>UZi=1XrxKfy%K}2a*{dva1v6SBAEH}3@DI<9kt8e~$KDI5b42$j@_MjJ%`B2m^?`MU8rYIc$ zbBL8EpT~IeL?KSozOqtoy*2UjsYZk4)*))d{n!bvoG%0Zihu$OusJptV0zj=Tk@*i z+@&;TW9)JhUz(Do4Q-<0C^tp zjO~>iio<@N4t?d?G-N|)+t`toFm|-RHb$Gv_8t1Nc#~oC{k6uS=igO_Ol~_KO1^t< zm|l(dxmuzmmNdR_T9M*T#Iy6Ec7J_PvLgQjP$c_^2yxuqmF@I!Ch-&!(zW37VHUG}QQ! zi5-y%m1LvMio&4r`5Y3Lx1pY`*IE8XBG-^{^lH9?9|bD^Vc20^18XZ(?F_X_ZVanz zn?TspsnA&+9k9zd-r`$l<_x?*)e25YTh(4<)DIm*j)O8{tiFHoX5F;|hsxLPQ0iW5 z{80pPE^|wzcVhv}+b`O@@VGO1!rbeXL~<>>%^BS_$#~#vETD&_ai}&rYrSyi@caxTTjY!^yCoc( z)*1F8sh6<3Ykc;}W2oHeOw5t;HK1v@ZJ?WQxv9#c@g=qqOs{eKx7hsuKKS!?#ygRJ%NPQ5}+;$e%zv%hn0ms_) z(SeoNNY&cnH#R@AgKzTMA^gh=mvj}EE|ha$d!qb1qQNK?7o!r3Ff*<=)?w#q#9gCL z*Mrdv4qcmtY*iI?e;X)|W?#9${(Q*6eT0v>!nsOG^lish}lp9A*rHFc2hNB7~3Kun;)si<{zO1(aH%w=D$w z;>gWaZ2K|!dzn)oDz#{UsS74tBoP?#Qu7IZgT8l}_4Q{RjIFlyoMp+y8G6O|Y z&ry|CCwusHre=70iLDo|j=L(9J28fya2@m5Dm&lQww=sA=J~BgCByB9r6$Za=gx?Y zY6Bd>DWgBA2FFPf3kjvmH@$wQ)oM3Mg3%9)ObDWhWk1^UVZ80l$|JcfJe^0yfE{@c z=C#>0f>}_8sYaSSa*4yIldzHF48pTPpY6{esd1Xwj!Rd3_c&dDa}TdcC!J&Pb$HBY z!3x~S^M0y>#_CYrM|Kt81Jxz$DyBhS7ZInG5uVkCqyweYiE{n<{+Jw>l@Uu>76R|w zo)v0yls?F3nW~#-~Sb$%GT!zJik`+*5kc#3r zad#ewOTQXgvQggili|RfovbI%Kh0eGMC0s8Z>eeiS3uLW&6(I4DJ|IXk-%2!2VU@T zfcg#Uu%+j-^HA<2&LX#!rS4eyNAvuJb779Q<~mK?9{;*OiWfmHUYf0+eWog%FkyRc zZZ;!dPuF%~dJ zC*{X7#mle=3ra0^yyw>iDvh>gC{*fY^&=cfS(Kq%29I-}PE>&Yu-~Z37wA93hB?v$ zlEv>x9k7Ph_f+NMEz3MDtxL3D&9sWUbc#|s)b#SoN&D?y2N!n3RQ0!b0p&CIHUIeh z?y{>Eo%5wn&wab9{8;3&UQjV5jLFI&F{;to%R6lh3d|Yy!Q0U`twL(b&bDx{X*b=c zFwn=6xB~w;+9p&RBjlUSvf@lqDLaXOO4#W?=K|t6L-i&(KN6gz-Mz|&Qq_Ljy}#~d zWnLxw_ATJ{4h+3rRkYc@O)=e&zPY9?*MIzJogE2SLJ0A7enak(sXu&DJYMx<#h5>p z$PiRaN;pbQ1c~G&wjHg;-EUOOaHe(OS>WAP#R$#5-UPp{CC^DR9;e5KcMlp>58fqj zgA{eYqp>4y@V7wMMp4bxIgdM&mxpe&z?#A9Sw=w_KCIedfdtjm{Tinlq&lWHc@s>q4QeCXvSLFrC*k3MBHT?FQ#-1emoF# zr@Do(y{ZuR@^ZQvgRvey+rZf zJjmQ3D0419DQ@v61)+Z2L!u3)W5JY8>|DV4@crCf$Q^-2aw8`T|Dto(H)JAx`E`EbMqd^AVl#3}pS|Qq$HIfBm5uLU6 z?+FIG%^yw6O0(2o1GGAK5Hrsn;fet*f*F>Q=;zz<$?!Qk^5joa5heotym4!veG~*5 zdJ48BKsRox6}CUs_Rqz5ZV7?1Yl?i+V;ivp|J$RSm7IPStYaTcXqEz#YW>;MTe;}Z=;WvA2 zq#mlm*D$V(EQu2YXY*MO813THsjEaA-}pB77q2Q>xQsNs5wFkGjWK-SdV1Wi0WXSz zcoQYG6y8m{X>~)(Jg@gX)v_$B*ti znn-@Ofo3G`D@srTu9yd}ViybH6R{BmIKE)v`5XpQ0JxJW=ps(gdA{xU-R|&G zdJeN6=juhp_+~PMaD#ZGFZAacuFB39Brmb=a{%SQ^o^@n=u-oo0-=Ndme%@}raB1?Lg~W(bwvN&Sv$@wGx?y&gcmp>8y)*!L zU6^cFxq#O6IU24-CK`y0kB^phF^zGnzSuf+Oh{Avsc$zrwlxjJPRbom7c&dHg%oQW z-MbK!vc0s07rrq9`P)3`-1EhGz_;rUe7)Ix$`#k;qn23b3O?hhbi#7L@5JJ*H9^6U z)dSwKlMj*)c;<6rbK8TE&CcFw9V58@PVcAOFG8fEl`1SfF;iF#`lcITFQ#QNCx7?* z*NMuaksf(UvC$K~dJHEnX-ll4XggxJ8Z&M!3HrvmHE9`o{kQ<_G51_vxIgE*EKu|H zA0F)|gK@OywJ`h z1-)OI&~W888QQf$6y2(TS5NL|HR{IK@i*HhGj1(DhVjwH(>R9`>#zjtI$bEv)G8GY z@hd0o1$;l?Iv$$j6ddfB;z!quy6R6KJ8GvVmb@LNxcQN4*aPsxh4dA-3Nh#9jhoNLz)po$$9GT07b1Ra1Lx^q zsYEQ`@X5H1a+U4E3kdb9D%7gN-(;|m>b$~j{2zYKXSKhuQw*G3WH@+^i%Atpv{Tv= zhELTK^(LWi3~f0fuNH;KZgP4ZosXx8qPKr7R&QUX1Wh4B=46LuTi9*oc9AYya%k>w z~APW~$f3431k+GNOLP>UeuA!H#yLRZd=X zY1V`?Y!{d{K}_;A5mLH{v}XW)#!__DhJAP9A;CLpTe@lwb9URoTuECH>;2QK%TP2s zb4;dB6W+B@-ulI72Moh!=;xQk#&mosEWTj{F~L%{Is4C8#8nD|`nnvX4Zk4?y=+A% zBn`zTi#}PuHpK_3$EM`kJ>sAs`yxh_@Xp`F&yd#3G;(^nb*p>! zX6i=#%wvd_mR>wxSeU`9(fu*hQ~ty-WH=`6*rwH3+Y#FLsv8u&@)Z<=#Y%YkT7NMK z8S-e>(`ZlRJVLPr>MmKtpI+<9_;Wr>VRup98gOl~l^j;Y}UxCVYaGLCmv@QhLWxHef72 zFOkF+T}N>Iys$k~(?% z5O{d8gzM70d zEPEw7yh`d!zT!-+IUz@Y~1ePleq1R)K&i6BD`&IS$wulPa({%y68! zo0*WjGA*C2D{VE+m09=*$iN>r%L2;i_Rh$H+1`5y38mxA)Rs8qI!wK|`hjt094HHo zr`UHr|1HFT&NhTI`5JhV*^Z$2S?+12@&B}wN|6_AMxZ_Y&rv|X7o_(8_4%h4o`_z2 z2fwVTULT!CMbFM?%AiB``sybD+=d5v3SjF}WIPng+yHLj@p7ZAr`gjYqfP@HA+Kwq z0ej3)7bRYxM)_d#hA&-bU1v8SNMndWciTeQV=U$7IgKf4J+peb^Iq@p0BwAN&6k|n z``-Q_sSX&Q=>=$TnhsP3NG;-j{2=el55pJ(WDm$;MBrA~w@a>EENCC&0I!KtgG9*l z!O-`C;!SKMPkIVUGtce?(86?`WtJOVK5t@e19n2U)-6OhxE{9+AF9r>!~Y>)Tt~Lh zdQwmE?dsox_TJC~ONO6%Ca#ZF+u~ z@Jj{+8q{=jm_e#DB@>hdTx}O#FYQ*^`L;;~3tIHOKVVst?6$S+a z1We$;A|U-pVZO=LJ7` z{{1dlSX<_v@w<3D_f+AS|GpsI=-<|Gc)vt6E@_NViF>>Hh=rpb^xn>iiSy{m;8O*Q!UB*b$CRz08N2eRlvuc1=~{OxXr9k50s04UM_<4F4a>q8-j zcn$3<(0}M23*%#Q8Nwj;Wk`i_BdP8bk}h9OQ8~clPqg=wc~8@rW{oR@`jYM>Uo$I_fjp&}aY5Y;nh7vy(+)F$M z<-|Y~SnkFnDaG2yi@5h(v-W1H{xGW0hd)}TUe5GwlB8DEaoU@J+Yzd|>ycIfd@kBx zIVY2TNbuJOgJY0=3Jt*H23=n}UwD$AmUnaz#0kE%aCLnh!vk-j`k@U+cs=c;7}gl| zLOAe|kh}wE5+8=8`!}EN?k~1M{UnBlh8C93`v4r9$L;iZ)@HPzpaA_1dhJv3`Kp2S zO*BL0dI1vuVrI70695T9MS9bO!8r(YU?Ww#49VJi#ITx|5ef&C0UCZqIMME3gws}5 zzTpaMQR>23MGL3JxDOVFBzu>3Tn#T+*2wOtt>uA}!s)t|AU67I!iYJ~gT{O#v0=e5 z=6*@iU&C7zm^i(%3LZgsfB{-o)p~nQ3lQgJa8A{k$sS-?C}iF&juQU`oYhlG`#M%c z0E3z{lh+Le_qPP{w)-E9vi*R8KIpBjs;1_)&FD;!Nk4MaKvhZF+3#^7A(Xd#rGGYwVZWidc9_zVm=r1enBiz%o*Ap%NUII@7Q3JX%GfPoMFBz8N>$DP2Z--fI0YvtX}s! zW%LPukK!jlQh-9#VX(YCCqU>RNsg18*e~Bmr9tJAg+TS{oEmFm>&2GgMc9D{IvZnvf3jf^lsftk)FFz za$WO_s9|4l3xwCgK!Bb_Fk74QO@`hN;C+pPssK=jO_Xta5y|i{s~b7(*7?3Q>ZH)V zbGQ_0BzQblym-l|CZVN~Odt9I$MBX;V9IVH`Wa&gnv_L6+e6CcU~#M49#}nR!OoOKPg36+r8j%`W1Rx=Wwj) zCi0gvZ(_UgND+(`i^CeOPcP&c1s*0P)82(Pal_@)j&sKNHCK)1Xe11(;B~vp^KN}Q z^aUG2N6p*e*Ds@>C%@73ZqxLf<(5u>a+&(TMK-qQ9|7j7cUdKl+u6EWVwtr@FR$4> z!<-T@!$)|BITs4rA1B2Y&l|-wBgpKg9%B6qBi;;bl=d#8638V%lt08PK90U({}q9 z>Hg;-;=y0?sbRUlps>F!Q)_>KT$ZevJ7dtU8G_hqNOA|w9i?_!po?h5oBaoD3Gx$9 zz3+7Ejc3BLCTj9IEV+gx?(#g@L-K z&`5Ir$DnVkE;H*lWV9O&gACs26VxU~7EaTtLTw{2)C&tM^sUi_MV_E~;@x4!K~aP3 zed0eW1SuM)UM_42ZZGgDPCBOdiQlc)<+oo5TR$93_Xl(hV=`44ev-o?o;8+b_A^4| zyZ)<6A8+&9WHrnErd3-jO8||z6kZE^cCBM9)cc@bT}CZtZv?OvUIctV!@o{j9D%&9 z^pzUZ-&G4J+xjc*?tBm!6A`g{`x6XH$HG!4AxKh;?*y!Zpvyk|niq+DEpC~+in?{qDF>(i~xbX{(_pajyH75$Q0DLUH6SPM&` zZYo5NqGE|O!cF{IgfsCg{8RvFN6)U1Oh-2)&KHn^9aBNCO#k>nHv18NhNF`nrZiKA zAL(koTC^dZisligX)mQfbP{1d*hva2rCM_21pz7D8HbM_mW1qrI+$@+8@eHtVDU}Su^VN#_W|6jR-K$=MXfz2jn zEn#1hT9e}aQ`L6ef{+~CcbSHVF27^xi&UXkZr7dbzQpjUX}+dEJ*BDGf4&wUiw|8` zDLsf8<=6u}-(oS<&huYaGey%HSbRQ|TSe^3a9{F{M@l%zIu`>%n?bF0I6e~5!QE<> zHd1dm~D#a-9)w{6%20l8XzfPLJ5~aBErXv)5VuhAe)!V=vR3YP`o$GG* zhT1kVEFCQNp`vSE>rm7ws9&f|-k``>sMO>vZEIl1M@4J9@gE}lwRglcj=OrOTElph z&$br(MkmkinF1dn~SENvW42WX*J{yq8BY&>?{nq(ti`SUS$z={6XG?jO-&v3Q0 zYHQT5WjFLFa^ec4KS=+4H35lI*H&Ak8u+ZJ43Dxl2HO6qB|#$YbNkoQGgI9@h!%u) zqTQ28zYwDaV`rU@4UE?W=21l7vox92d|%(+t3*>NYcuJoc>w@>i8h9u@|4Evj7T{= znK55XkGhDLzE_8SpgzJB+2VI3#hAV1|c;sHnq(Q7E${)}fhPN;_$; zjappOsF<#egMW^#KYdP(Br)`QmM@(oWkMPaoSU?p1NkowP5Xl?oWUQa7w25Eer(CT zj}3Pyiz#dQEDcz|>_6@9k+KWm1$ZY2z$@pyoO|)0x3VKOdBnTh9H{8&cH-?2`+j3S z_qgm;Qv1TJriq7#j~~UsP;SAgs}Y*vbr*S}Wmog+@lN(l%rCM!oG%^)z+Qq-1>%SB zV5$xNv==+DE8w(!ylghM!E0yUgZFd4T>vNxTFOg}(v5O+67n|m$Pf4KbMV1PXGI;g zDhb49Z$QeX$Fh>oVsm%Gayuu2dHvr5uQX2VDv^#6?V@fAV&r22p4nnkaJ?Q$s7Ludo z#T~{E;=!V$ylm`1>~M{v?{%NxOSNA^T%3Lj^kud=W5VfW&%NI&!3JS0pj$hkuP zPZEVM=>3t*@pzoCCXX44<4QI^9i>tk@{0!%T*h+k$ch@KNc7sw zBs;Jo97uXITHryxJZ-$nnBJV#Ios*#9O^XEWKk>a_@vtcZTxrIUk$Jo2x)rK(y_x_ za06+shU-!7h9g7T?cI`&n=)x+nHXI%Vsq0RCchqy^`e}Gv0gL=?Q@qkUt#esMBtqI z@Ij#SmD-9x2=G}GCSDAv(oDiiY=&$SA$Ohp1KXE}LH&cLXb?h};uuBVK*ET_WIh<7 zqUh2~LQe>;2fb^`I_&M7tc1ZQ(`)+_!%eKpJ1+}(HwDsputeM4Qg-8cwtU#Ck;6iv zxzo>Me$B3w_l-RftcTkpBSyXnOtc@`^MdcjIyk&Z5OZP3yibHntT+MwZg6~YFDBhs zDzhkop#7%*y{5Y)*W6kdNrokM5*-6F+bGBt=eQP z>xr(5VOQUVYV}$vo_C>&gldbKH`ZL$HX2wfDXN9$331>N#582ss$V{`M`JCmPpgg| zBl5EwhM|z^l7Wqp)Na;UjwNX~Ia|0l?FgI|YX-rgC$x1zH*~>Tl2Q<%vHmTJ^N0~tT6stEQYjVHWsLloTa0SabW3lJ*_f@?1tZ)>8$>i`-!)T@X}BDP^nx?F9{C;JNtDxLf`hHM z?+CL{U*Vah*aWSqB~FLWOzFOw^k;4<#G{q_Ubt3a`uJR6Jvm^m)T)4r+PI&PImQ)D zG?8B!w4!1*03MU3GxmnHUeu@U3}(M=PU}bp&ZYcj6JHe+{0ZS{aOM5(vHUju+f$Xz z3y|((zV3O*g%<(dk7`muV+6!|om`*SgCTq#SH#qRnB)LpNzg?sAyFmK)-jrh65vk5 z|8XinvevPXQ-_Zr=p@9ihcznMSb&j19Hwc=FWPk7PdHqpG-G5>nLhe9$a9%G3PVS> zG8ZMX7goC+op@|iBWBjPR%(1X&`fx3356w>%Z8cl1eQ#tW9f@-o#!W8)1yl5)Z$6s z8@_4m$Nqv4PKheEc}Pw-23E@V4=4la$B4D@Df7R&XBv>+kW_RGg_K97fh8My$Ky{B zyu0;?+X6H~cLu@Lo_sOa;4#1=8sa*1VzEUS2^F=?1r6UC_MIuzN5jJ4#bSGptye4U z^ZFFIj~Npi!#&?pP>8=dliO^y)~V^SXGzEg@6Xg4q67Sr-i0#(i+r*UMseu-dD z#h$*u2+vkdBa~!YT+*M5 zLv9DBSsi&Iryn4>H?DMZ5|!K^+FMYO2A*`;Ir#%W{#BNI%s<9-oY*-{>s6Z<=wii7 zaE@r=mA>aO7?ZRaN40Y9V(V-pl62z_WnW?}?lykQLTj%owF3<7CJ{D{jw~V~B88>n z)dA%%9Hd2Es_+g%qdh_mo?r)uZ-nRp9I`1IC{Z{CbF33uNDRZVjksz-u%dI-IUYjo zuG0xeIaMuMdK>fgUnBY%j-U9Kn^Sh*d|kn4=A6KG--Vy1tn2LLDw`66f}@!>7R)o>Hq}g_=XQoaiTL1t+CuNtq*16gRKmw{>Hxrq!l! z;b=>IDLS!64f?!eK2pP@cJ8FkhS{ES-f3APZW`<1(oX%Snw||4o2|ocj)Dbu@ z;%u$Z6VW@jc&g*Ef==Y^(%9fD4ZW4+R{wtUQtjG!yZpc+JGi;InQfQn=j8Wz3FiW{ zQQ8xE-I|5Q-?LT-*YKoC3y}Jlz;WSTfO{!k;(9I1O~p&~-z63)`^S;{Zyi+fhU)+C zcccAppIb_Spg+*B@8r{T3;);AEv3Na2d#UZxwIN3y{TLi!@|P2&_rmfVcRI*h9#TA zXo&qP=y6#H&`!?Ls8a+T5+U$V9s7;|~^nf*^;+_4O7 z3`Ik>PQy8P6?hkY=gGY)I+(lRYCB@C`0X3Rs|AyB>i=dXIjQ{^LI5L3- zeHt$PQyPZZi;Y3L$F8B*0+boF4G*fz3-oZ@9%%SSiV<2#Lr}4wAGp@e(AjQ7BonyK zWBQ_0sxmS%BJS>7D8vHMy+N?Ds#(PU=aA9<4Ozz21zC+wDW5l1HN{q@+G=9^mUqf< zhA7EuK66!UX-Tz3#}&OlbOZ71R!Dlw_{*2S+Zb_L>RFS1f8kbFiefHKSgwuo9&&xv z)hIgy-Ak{w$3K9zl2mllJ2AzuWhnRyA3n&BfAg8tTA?J>`{6J9S26o7dF?eeo z%f0!l)nGma@ELv8g+mg~>GetME%x_s+%mp1qHa|mI9Hs-Hw3b#bkb+M;aYt2-cgOK zZ7Py`Zmo|q6dhnu3*15r2!b=T+LrV0;N-fxy^=VjKDe_Hzjc-lCDqedZwd~}{ReF}sg^m>Tr!JCrKZdT+ z(+r(~Jpv>V8>;G1mvcuuP0tsoD2>I=Q2yCFYD)tk=77!HR5Fc06(Vpg(@Dp*fg2EE z*o1A>2b2tOoYO!`32llU`4%L}A% z<<1bn2?gP(_&t=Fb|TtE{xp@A zl#~Zru~Y8yV6C!S^v|%?11g}e7$WHkyv}p(d7pPmC7L%~<#B)^5BXMIsGkolFz-!?0^>@a<~aZ^RCKGXt%!t(m=U8qX#9Tu~Ynq2d-U9s~SB`4KO>1vt5&>(Ef$b_H-@k zsJc7$5>-%au+~(KJrxa$QN^##K6F+I2(w%WLgK!+5!kAM{A!2E9(PaI2>XWtHW>v;y-E0x9O8E?>4 z%IL8g&2A2Fkl|HaT6f81dy(0*H-tEjj8S^I7&T+B#~M7C-sf(DDzfmbbEw#`;gSAq zno3b;c$>>ho>rM%ZzzS>#~&!%LTxtke~xU>+%DyNgTW_6-k&-rYES-J)+y56^-i>5 zn9hAE1|6DZawjoX@~)V-$!ZJ>_uM2P0v6_-m(T=9Ntu|WSYrWSey`r~JuA=b*=sFy zk#zF)ILmI|XL}&s^BX|OqnO;})E|Be;k2%3^| ze*eV}p4)UuTL|0a%;8py0~)=-GcG3(ltNZ(bfiM3!@`=|_G$ZTI8k%+*PM3$dU0s3 z@j!+s_o95Hl!3Dc;-^*U#C0ZUkp+i?S?PoJB5LK9&{1=Rf*#M036XUh_LnV0-OU}4 zJ_Bc6_-;3CgbX9s)(=$nw`DF3OAsgQ&jWXBK5mB2HspkmNjMVV8+g8pU^cl<;-U}z62Usa?(1nVU!)tl1~WSRF%*9J3f z_5SC5G`BBgdQ2y7xb`OrDBYQpd17FN+wA)8O(?{4x{dx6FO(7l1c%=WHMEI_eWl$tr zF#Tn8F4#`2*g6e#XDNslSN_!)FS0Uu@XpVqsq6ASX_sW{z-X0IFyh3Vk^ZDY;+v~sUyIj8 z#T4A!|FCNG-WYv6lhKS+kz#Av1MFEv;d#G47?@IZ{x{9Rt`&=L`69WN)4p_{?Q>1f zK*2NNq7inBOG%H@I))&kr=1s>LOGQP?7ka-b z02eJCV5HiEh#X&3a<*&j z3I#^U&qRIWc6{iM(?{W`N5R*2j=6O8Zg<+TtkA>S@$3YuVRvQSS+-npf#f{f?&s7< z_bzEcN53JKSH<{FI0={O;y^(N>)E$F&S6A@X%v{7XLp>R{-)Q#Um=aNPTKwb6s!;{ zf)Vw>4%<6QpZ97~z+C{tMRUL>uJ8d4MGwVhw?u03g|4HdVgScGtyFf3(E|H4<0bpv zz9&A%-+_KH>%(Iq^VV$ID=4dl|EIeVimnDUzz{``sZ2c;B$S=jiXYbOb$UmJ5tmQK zNYv5D7`XkNs;XXrXB@1j9WB_sfWTT`9W|r+x{k_iCnwRJYIsj&`FH5$*+lxQ56Y-S z3`STUmBQvwmHss6T&DeDq89so`A61saWSYDcE>`tu-V^Bb~VbLX!(jd|9j<6XMlJ- zmfC%R&oP*sVLheGY$#Wi-2eFpQ2AGgQwy&yGqgM_7&8AlFh?1H((87FBxZLWGmae4nT%mhR#;u)AYik9v|yN#i5;S zN@09-{<*AMDOtXf*V?bTYR+fG>oc$RsQbfb8P>-;I^f%m*HSy9;lPe79=Mk*{P<5G z|MuO*4IKkdj1xn9{#lk=ZYPZsGvYg5w{Fp8U+jHDnqGB>Py$q*iF_!+$-(lN2i`HA z)yNgQ9}rSR6_LHR4C9zDu@c-GfU?&)lT(Sk#>nYM@*3CeaQK!_3`G(xI|NxjbBuW5 zBfs`9)}*pJLAWmT@^ga*Vtm1f4v`Ro7PG;YaH{j^{O?M#x;E7Rt0@zWMr@j-{}#zx zX&Cm6T~Xzl(RzZ>+~E`fdmvl1ti_vO-H*RmJ$FCviNIN~G`4v0pd1l`Dxx;w+<=emDO9wXsh#UBD zBpoChbVl_A7A`|+v!~$hGoH_0$OFOgLNv_SD|d1HG(?#Dg2Ppr2B{d#I_bm7AGxq* z0+-}UE$c?8Af6V9_d4!>dmGC!@?C8GCWc1tjTl^iWX5;_ zIo>-U3Ej(9lerqLIl1waKY3jX&7N-!mGvGRB(k@BZWHiNb1(+=e|A~q`{SKk?$DNB zfruCym|&3u3O$XoGJwn90tZ`e#4?N8~Iy{x7(@n)W6t=&VpFY za;Zw+tn^Dp?EZXd)?5%ou{d3WEsalI;0ay1{wKZ8@C_N-&8cF-W!h6pES*LUAGbN9 zW{Ev%Qvy1`xh>+FUrt$k7;O;5F0={RB3W>5F87vL_IK`zhn(pW8j2iWcjI+LYuOTD z5$-B<@N=QP5XxnEe+(0p6YA@!#a&;Zb-$j?-4OD{Nq-BA9#Y}2PuJMkd0&KmbQj$d z%H6N6rHSuJ@O-Ic=3;IzrVcQ|!F%Lcm5N4k1j+J;7A{OSm3!=e?F@r{IwKdyeEiZV zK(Exn303a_qUyv3^3*C;U9SWzV#W=cb$nB-4Vn$stkwLQF5cwNp`|t$(_w{CtG84k?*AYb1h<6kk$X^4>IxLyYkgG^v(5wyewaP_OxKusu zO%VNlvSLPbAkw_~fqtI6#7Clb-v^OxQDcmuhDtfjCqQR#^v7vrx5Q|k-F%CRH7NG4 zLvOUUKpGDQG9Y|0#MLqI)&f`B*9|^S&ZYWWg-|JxXy~5$SLrX~QPEijq0~(e(@`|} zEgYY!4i&f@9WFd1&wo=rxmgOtab6+G?WmBe=%P#fKsu2r^xN?lU76f&;fLdNwPtx_ zzqhxQ1@{GmsyS5UNJ5gvrE9`U&DUGK3T%8@jiN(djEPzj**6lo_9yJN@CqNCTCU69 zk)A*HFoMUg2J`F691Z(%QniH%(BU3!Z8yr6Trr7$enGJ7QN4wyx3<0~GgR`DueZl> z$t|(Xd4~Hke?taMBrSPdt8q{6$Ex$*eOzH#l(M_N(tx8;*Jn1;^5e*t9BHb~p!`wu zkMKP%QCI7-5qJDcQxqZb20rhch{n!v^{oX)@(XOApVp$lO$6_tZ!_8I=C|sjX%{uE zl$~`8UQ(szQl*r)z$LP=6Q!ypr0@Un8S6Q46>R8Gyo}Tl+ZKS>t>57J&N|BMVEg81 zC+U5*Dobu=CHbDiQ`8odQf=nsHT3- znmz7++Gn-7BUSbUCd;-NI(fR)UB~!o1;fhUJ`cK>{9`#zYhkhau#-vNih9X&0f@*9 zNl?1$$s`LCTBZ4z$Wb_411?`G;n1=m5SGCeHS$^g(zzRw!7i-Wir2zG)HuL#B0EVs zs0F{Mg#=pIT=o!;-a!0h+)%S#%l&3c2O(=y3n2#$9$y5DU)Jq1?)k+r?pGk^4h|oovB2LjU$|8L z$xSjX3uvokReEPQ2_hbVdN@vkB&YBn#}S;ZAXY^OwbFRLoyHnI_Dd*Z{~NQ?&Hk$P zTVjb#$JzMCxs|T~!so<-8$zGSZbdie(^;ZM%Vix^K8wjLKd}wocD1j4J6dSYFSGEO zvseqN8<{&Tu4^x6^&KNs!wf3wnk8mJgUH*ra0_@eKW!UK0fc7E!~ul5=nF^1&RWiS zu;9d4-{D(>?m~{;X6VcRtwXms(qz^AI&~$r;H&F1H$&^Lv1a2=&i}5Op;xSq{6pYAUJXe}NxAnsTkjlv)d!+F|KFN@?3OD_FamM> zao-w=Xk-)O({BvF!Afe3HLVz<4asdUIk*}9zO)%Bvi+Afr`|uUL{w-yxXNiem{}wv zY{`B7&^=$dW~KkLZ7X|9bTPck@{$yh@5lKsiO(S%Kx{kFS^Q$}sdwZ|Er;^FT@`Lk z)xc>57k0&bN2N{F%kxwM^p6{Eu*(XE!>`V5lm=WbrAJCw8nu(>s-IHn(r^w`SQOn` z*B6 zJ=Im!)iqVmdCob@z1ts*oc(FDvV~>7_NL}7&kAL=;1zWHnK`IzA2t?tsLPt|aMV9; z%R`pLA=gzD0gYimvi15);_YZ^a1#a%l5&KKk($cuLALX1+k-E!e$Bia#P~npiE7Tv zHWMZk|Kf=*sLnAsx&1H-7SvfD@#wgepyws^=P?y_#}AZCt+pqdnBX-@Cv2?K_4Sb{ zN9=T0dbqpJH?0`UIbCuXUOVVF84wW|kx4aIPzjoE6*5a-*0CoF_jwl}Gpinnln!b| zcxA~0@%P9|#s0Y;saQo8tE#WBT$lL6coRO9`K`1s!8p^>jefGcJ$wO^)>WDL3=#>u zi|~pLQt$8YC3R7coGvH6UpH*3Um3yCWGNkJiYeMXHdmGHG9FEK#c>as6;0HOc;GS- zBC3sNO?-tcg~o)@T5k^tUoV>70PmI^p4C#lQ`5V6i#1&@+{XQ{o8jE$B0JYK@zPk* z=g|qLSn2ppME-r5ih*cPIpJOo`IbEi7ZmmHSB;&>W}mdegf|QDNtdaGQ*E@J65$M^ zf-2u#yq-FT*AMToZ&8gOSDKG$RxYL>43r0uNLmdC%a3JXRe_Hpv%30x73iIzEoAjJ!?^9mn9%XPPyZ zdetlxHCp%o3rM0m&9}k^m&C0VSK--J9JAY`3V|>VaXb9@a@01;b{`p~YE)L-^;raH zBE6%C`Ls;UIG5%Y`cHU1lRaS@{4n*Nmk(c#f+FxxIPKvU{`sR9r*>rZxDjUB_oTK^ znB5g?HuOxB+vJdEv9U9TM3e`Pw<6YX^i5UC4nvC5Z8+wsYgbvj-hk%mEdX1C78P^W z#bT$+Bcnj1Z)$IZ`95EC`{+zn+(VQGKiT#5KQ)Gw7|kv4;{M~@JZ3Fu;*r706eiR9 z+f}Ea2-DX>tp6Gp`;)DiLS#=%Xh6TE+# zj($&lGD*pIz+YQ|)moM1B@iC|EyB?)k&XoBkD@zUHf)r^_7|I4S8n(vUh~7(9${1{bM*9c3tr24duQaW;BPNQpX0VSx|gnm`?sl>fG*V0FG{N{0ZrFn zimnaruR_Ad`tQT_GgML%L5nw^WLZ@6&yy`zhxJS~Pu;2!kYA1K9T)0WEf3(&H=KGP zyv3fS^x9;<(QJr1Vj%`Wn_lV91G4Xk>Pg>x?WP~qSxST(;sw@+^X(ch!^BQ^mNr;X zJ}^fP9RKDHn90)06rU{rId82}x;O%_Q#Y66#$AO|^4WzhFLb-`)9+b7cI8b1o0w z_VpVo_cTSzxxv|=UNp}{Q?nznk8mp8u$E@Zv;*;qc~(|o$0Elf&r5Fgi$sm5BDnTp zCGB#w9pMg%Hkn5E)_bc%I(51p_cMbVja6>}w;;3XW)KVtO;=^0??D>^-Ay=kmOt3#&~y$z0}JI zu34A@rydS3rNkOLv^Eivo&(U+7ZSwnzKN=}KW7|Dm4(8oOD#QG(_LxFstQ23Q^^(y zPbQ-!50<^H^{qcn)&sBiCvRM}vS&8v6sfj{>BRny1~HG525!=_-_?pocCeZS?x1$h zZEVL{DP5AvL;7K(ItS)Xzup8)nRyK12l4J>1?>PwImIiIj8-q6|m4o zPH`$wa2>+oc3b=PmGoxXzkRQ?wv4LaN3z`;8m1~Ivy!frSKjzDZG4IjZnK*X+&wU- z7FIKRPP<1c9VPJhwZohqwPFQ2E}9ogAFRnv3REr0Mu)CT5Va~s0%>X4RK|_(3(tS< zK`v+MCDZB4(_y9K9V>Fg{U= zU%_Wkj$&YW4 zY&SqA3ybt-h!s5d*)2t~g_2?fFB<4!9oqdIX6vL@t+oRs+7m+tWV6S->sHDZ-lb^( z7TxJQ{l#Jl--PlV7<1596xBUmB-OvHZKNC3;=m1AT z6p%t*rilEAV}>~tiyk8B=n7MSKJf_T#f7)^HsLd6p5DB*Q!er#+`!+wJsyp32CU@% zCTNnYY;WOXm!?gB&Z$9kZ^s(Pq?3xDIGM*<4=P0FUfUrm$Jg9u7Iz%`7C+HDG3}vQVRX+}w$11ZFO&b2Cm&N# z%o@Si=!UPf!vEKJ$is#@LL!kNAbGrkUs(N&&MYWKN!VVU?7RtF`CW)+tmpt<>%t-a zqz@1iKMrEAIHpfL{0^G^<_L;$7aVARsiEug7C#k0q2SGb04V~!Dop6RA0_1lS4^y{ z9dK7< z2OJ<5lUz6NoWfYl_>on5IQ4cd#@`99NTrxXaFs*D#bS-CIyq77cyxP~|EU}Mt=0-G z6vf6xzBw*0xmq2w6w;|AOq<3CURu_(PyNp<`%w$mR`e|?%G}9_vv@#~J76BbzS)4J zaI@Dqg`6zF`kGc=MHI*pD3Z;T8YsEVL?8&j=Mc|y2UtIjzvmTzHxJ+o=3)Ys>!g+E z$QD$=gyWYDhEXw)^LkzUU&%J8B!$#eRQiC^B;Xx!dUcfm&>oA4rNChuT@`fyPzU@S z?*X&`C$bA5>;#XF%KS$~9Z!^NGeG?>E%J>W^Iuf@Zw7`P{r~p&)F6tO7{;%RM4i7T zgc!o5fSSh_!xnFnIW9|#;MDznoZ5f0aSVV-7Qn?1XE#8+g4@3IaAp5a7wRvRHyS~q ze{+$^U{FDF&bq-MyE zjH@=p?D(-iMiL4|Z#{}p(3wU3I7x0fJ5t#>(;;*2FNl#RyA!=9=pOa0M3mG?X;w9x zvgdsneyz^kfWZF@rpL~NyeyvAH!kxLpOby1hI>`1U8obj9N_jQl%e-x<~0NI!Et9SOud{#gMsmcGSC-KJT{_Y6brsyy-0{6AQ3G*c@2?Nlw<{42w;D$F5%I6KXi{?pqT~ z4|B&CB?f}Cv)n4`*>Vz16v6;peoNhpV@BEUf787L)db9P6D~AyU4tkjJtq`!LsUghVgm}*EJXDJBN>7&@+Bwb{s>eQJ0aoyU5xS_DnEvGfWJ+0a z{QBl!=pXE2`NFmuwDMQ}ns+5KShJo)ZCydSuMnM7@(B65FNJV}LKfuv+ac!xf_Cg# zFUP?*A?vOZB72P}+&k>@gP7IF%L|6WA6G={d&T=fZNR4TiIh{7Yuk!@zM1q@X6S8w};Q z;%L33+HW=zNffuXL7T*K}Kbi?jXBuY%ug6n!ilfqgWKIA!WMLP@S@pPBj~_Rpl9C`rL~xBM!r z-2sd65T)K*UUCIZeyKc{q}3dVb$@s8edtJg(YWYFH|vHAU#lw!5Mps6Tz=gb$kz{hn9unE?uYZMXFO-cZdM zV#P2fk)mp`?2^*=l4Ph#g*hh=t&Rzf_)kG(CNt|@#0^rLYaD_CWiV9 zJZrJ~PerIUC8^+o#~?!>>D6P*?`-hNl)OFBW|L!cY5wyu7qkCQo{;1T=&0DnqGP?9 zxj3ZEJkX+G3V2l_Ny28C+re7%&&9_pc?ADXUyYnV(By?Qg)Z={X6x7+OpE#Y&D+n! zp@%_b(Uh3nE;OO8KXT5*dfUGdheiE}Nj!ZGL}{738|)1~zt&e-XYEC}7SfYJa`d2B zqx|)~OJT7j=@bxik1EG2xmDR?!*JQ%1rrm5CL?}gP~To~PV6jz_Pjy$!Yy$dTImy+ zzm1>~)^#WOqyO{AlPsE}(X0ZoRvobSw{}UZBDB8qlwm1zfc=<8*NMqT2Eg{_WDkVc z0p64}rK3Gg%*C7?wFB~o^S2(@bGOTp4};R_ zXr*ZW&)6TLso_fiH?|;31s8xY6uV$iU-oAp{E)$ti#mzz0qJOY_f#j$BwD+x;G`dl zu(cjBDFpsB{RSaBy72C@hf%2@Th@_Xa}^}O`;syG@2XC1dwZKI0#X5_K~ezR+!sGr zoVhh#-(p|5)YMvre-5HBd+rH8?w&atM)!Xg`-}D^$~*hm^wPKDjeQhI7uC@>(kRr> zU}f4sY^^oTZIVsO+EZe1JD`zSx?mIb47a-Jy)rzUBiH=tpF0TB_wfD{=Ac%ow@<9t zw+*lfI$->%SK#EvUxC-G#@dq*1p3}9FeII&h5%&IP@!7>^|uVG-Tu%ZM*t6+qzH^E z7CBu`LSS(ROvyhKS*G6fip=ZUp;O4K9(P-({^2cQ(7&f0683QH53dWcr= zO4VkTTuS7-Fof5EjWL9jeD4|&D_Z<8v9=6(RnuM8t4Th zp?VIGEzZ-B`Cl;VPb^)HfC(S&_&94F^boKWG%eLX^ts4$J%~UFmJ&f7P^zNKLKY9d zj!l?GGVh@IGnGP%f&*0$;5}|tLcuKyPVn_LKrFbNpl3iK)9Hw$LO|2oWo!VeIPx_w zO3&tmtDRW!S>S5&JvFMg%_+lteZ!i4=nJg=K1j*Q;XPkpmIW)%BRL-}1_JKcXvxXR zz*EY^vEo2gF}WZteFa0-$wwG?<#e}6%S~x>y+Gg_&0M)g^A}hv-U660qd#3eY~MZb zBymQ=IsQM~t&tX&=sz#O8YzpBo|gEl`&we=JWmWSl2xU$3BK>i_8QyQG=a%@h_IKp4 zPxc~T^OKUR8qWS@Pvx1{@nT#be}MBMS%c`Lw<+^id~i3jbewXy;6^G@4zZ4~Zfn+X zI_#NUpTwwF;XUQ^Dcv}@dWYPK9JNWiB!S@YYxs&wtHNVoJ;a(r0ODq5l$s}9g3?Mt zi;i1{z$$N)QAO&S$lBp@5;=!XDrzp|t1dRz(?w&<`w0u(d5J-XLG@(2qHo_(@N>gSixJod{)Z>TuQ&N3jwkUIPrCg^anSd5i9kN9!#oX5X}lzQnk?i40yMQo27{*CM1XiMOb;JB3uPF z2=7-)dEo^upsW%F7oYei4NHH!q?=E4Qb;imqm$oBP9*Cb3`G1gl6ciLjJJLc^I<%Y zI&;#r_ZjMSt^Eg~=yPj8LSpY3mNMyYMf>-Ef4#09UMz!9_8=vRKsr1yKU2Z;RoC%$ z{bFG-vD^NUT=7Lk{cWMU-b`$3^FA6w$a8bGyXl{(`D-N~qam{*G&cziJzU}_-m1s! zvrMhG$^x$DS8} z*4oyKJV|>#R~=Q8?w3%qRzs~O0xEntwV>~P>z93AJ!Azcq?hrlFV%fiJ@NV@R`t?= zf7j91mq!gyDMO#AsHlHy?v|j=h#Ps)6QFIy`jKY|-{)3SO*&pFOGFPp0j_4^dkHQ= zFOxnB?JubTIdYDo@+Cpu$3Lw}o#2S``h+lkQESOSJDphifn>i;hBQN*l8t8iRcE)4 zXXlCl+2R9g4GRw)Qr1(KtENmG#PJ4wd?HJv?+;+g{Rf1t^Yc1EGInC;1jMC!lDGBc z@9*6hpgHpPS-0J@>4k>_z%S$=qS^eP2vPuX)S;&GGxKXARbD08;Cr@W9ejQ#?yxVl z^R*}MQGz@@TMu3f$1NJ!(|JVeE6A!J^G?-4XBz=^NafQDFXD=}2IbM$rE;NNqg>M( zN%J#{nJ1@J2KVE|R-m#X*2;|j;zv`%!wB!y$nsZ9yZl06^*RKq9Un*>?Z~X14KX15 zvGFV^DaoR&EXd(nS#>h4Q8VEep>(Mu3|@{%<;r6PhQ=|ifPk)yV{ZgLtMEgHviXK! zJY0~LcNgE2j=@<@qa)wUv@lDtl<+%`#m?QTUCgpsN+U@u#hNGNqqQ%*{VgA&4_V$A z=Ko=6=c)XDTR&{Aw)HOyEZx5vV9Jj5XywxvNs@IY&6SuHvBR>Ys7aT{cn*dpNjADn zr_t^lEFvLR7O$-!S&3(V!smc1UHU;qU2oo8Ur*iD)vu_ts`qpbK%eGQ?+@{t^V`{=;#6R^5XklRWN+`RH7# z-iYiHMUXr3YbK5=Dbez)#Kb6fSbZ2^s)nV@15VE&q@X?g2fF{(y zA>+ZcE)DHw^M{Zn4+s8oi9;-Z@;U@W19($Kc3dr5pi!w%1k9|^>dq0})qW1CV~&&< zRT6o-+cFH;r->4rOgjRi8XMddPIG{#rCplx8HTHPy1SvE*|F*1 zHPcc+;$Z#2CS*|gb?$Lrapo@u7O5U#Xta76y10xvOafeyLP7^wYF$h8<&L;#=59#9 zYF}gba}U?55~hKQf%%|ZXQOxY7lna$94-WY-@9z6NQof4JzMxj$!x&#C6J1Zcj{si*4h9yyPIzfI&6)aN}WID*h)|-?t z_0zU}3%jnd$KeBChG#?tH|L~H%`WfOaI?Elu`Zr>g$`npv6g>YF31Z(R4$tx5-U@~ zmPI)cW^4*Et?HAE55_XdeTRi56gcW_lCkj7!PwrIEq3(%$Ji5-GFX$Vv}cp?p{JiU zl?{=aPYHCYW+W(2p<(8t&dkrfC*F(zmAg9W(gWGqahwKIjEaP6EcXw@^v;L zlicB#>@OG5j*#~hCH_VxCWo6vl>(xF&h9+S1K?#rHd1*9pMD=T#w8?l8`tb_W_aJx z^+%%4G08o<&KWfPG;8xGdhnz{)c^_~6xyvhbPJ6RV7N#=)o3VRgX`NJ%ii)azbIq1p z+1#=9e1sfllf4Z!D@m5f{7s+bqPz&L@pKT8Fl#F33`XceZB~%{Xg(@OfB~mfAvsQs znaF=#8Z8qmvsFhPe-#V{KO7t!c+R;px+)j_ad^0~tJ3d*w>w_`6dyxu@F42M@>6(o zG1$(sFNYS*TYw|0aq_b3S!DNlFu>?X#xd$=C^jUVMb1kps`P;T#CXU>#YklhutlIg zI3SJY2n|$qF0EtVB0&83R*1*0n-w$2EWzeasI9MgHSv)K)QPUCmwdriE{RvL0q2(8)$jd z^MP8&fkP!>x$W^Ie+)Ts&Hh-B?Pxw1Q8#Pqs^yyjOZS@pKFR-IeQL#p`G84MhX{+92? z@pFg8BX&lU0p}-ENrJg1f%3l4aQ4TaxwWcA+FQu%>_J(hhyP4-bMuzDn+pcjF6`ii0)C>^qy*zE(hQGx zSj4Ke5$&HL@i<&#J#}$@PL8J9*LW#X#)is^ipq6f>&eD%qPvQJ7mLT>u`YN;Sc<2~ zsl5~)6YCk;?E1$5u+2NjFd0k9Q@f6@04aP|EQIK0Z&7FDt~$+WxARy}0rE1Zk0&6q zIUSEODe~+r!ByXDTYj~85{i_8TfPUFv^^?n+JPb1G}MmrDW!7C1cg|bm{j;ShEiuF5Js)~ zLg2dWy{ZFdOiawa0MBeGQBn3dR(YzIDpOP!7S`=mAF~KJT zNxaU4CnTSFcpzM&qN0zKEx$CH?DJMDEZFo*I)F3&GVlcp3kwHIrUOxA0|AKGGc-V% zGkrA0FCQ{|_#oY}NfP;xE<_KE<+p!J#S*mfT6(-05KuJ)t|^LA0Rgwd67=xk0SqS# z`7a%Tx#64hg3$psCZ>Y{Dm-=VFj!sN0=zrK!QeBt_IzmBrP)(ZCdKrAaJ6;mE)%ns|TA^?f9zd7+7dV0z zxB>(W7gS(yVCcAQzXhfx{J$OegGxG~kTvSW>%_x691J$y)5`>UE>6(+S6Wg3JQye% zRr}utflHrSfJx0O?WMFy`M$rm=vubzLA4YG+7`qP|I!pEQ|^*$+~?xD$pvpO(pT{&WR? zk=6nu5D5fnQAr$sXw(D+7uO-P=C!`9TJdUdHYMs|(9&|*9A{x>ggqzqL@nRr;t%XS z=S3lID0y4AEjCD794MWKsc`lq;vA5gLk0#vJ=G`RrrB{+$ZE_p$K8u=1e(4AV*=j+ zVE9(Eb>d(ubh%o-4O^v5+ngzatCJu;0`5b7rX&?j!Db<23RdGYUyvIu*D(m?7O4@| zjbYRI=~s4H6_P;FXPjrB&0e7y%i=llgQ}vPcVArVN_tNy|HA1 zzA>3hfS+*X^qs*KD>9OKW*Kk2xZ;cNKM)HFB=gm|s}@)^4}vpgdKOgGr4n05XA5YX zFUKcJ6?cZ8!qYh=?l`uaANY62j{qZfAof{ojq+r+&w*b)wb{=`cD-l~5kFHem^Gi z2tRoTj}HzURc`)*L(i^1DwU$52qggqQk?Meo_htnz-V&Bww8~g2c^#910~MrxF0Ku zbi>x#)rPF=kiLXjx|sAQf4N_2*Pcaz?-Kk5>ei0l1M3lGO?v!@(j_E2i~KuNjezVH zYvI{J*C&ETtaGjg(}8MiMotizShq?5WIbo$dh_f4^a>TC=}iwlXFVtMPvhvAzRE!( z+Kod0GoU$gQuZ7op12;ey>~nR8wY~~l{Q|3Cx1pZN+%fYip_AJ#5y{s58ES;7Nqag#eRZmU*3>7itj&~5lVKM2dwAV)jvF=9wOz# zzb^Ex?RK0sDE+|9%4@{ljFYI#Ar(;oUI&E@IVk6THeg^PW0eQNFp2eVS#t2p8#q2S zrzqI%3T%#PJ(KW+6$B2+`Dd2EMOEC&r74iXhBp$cMaXYf;f@;>q{MNnu6s)-cCvM# zbku{0Ajqm&*${RvEX+$p;7yc5t)6%qH`4r39I^X$b2Sed@~-fQoVPdFeo2{_`))4R zYA;};_mSNEM9UXzK(VyN!q@<=NYi!k?q*zJs`s0;{}EQW?l(V@KCI+Hr)+_HVi;iSn-b>DnX?7w^RF0S7e%ln4eT-<+faqX1 zuxumdWG7Abe0|fEi_BfXFCk^4a&v2sV}!3Yp$)E6=@79fEI_ix)3kUz|Be&CdE3wF z=)_^D6*c?4jWPJ^HG`H-StFvAcEMz`)%coI6UFs39y&o%gL9&}UnOStc1dCjcK@q2-7hqZ%32nh?4Q`KE=1XXK5>c{Zl7@?CiX4A8UKR zL{>Plx&eqwj0PSHTN$ne-e@;Wo0#4{B95`AEMrdMY$|MI6R&QarcUUzR-k?hJllSC z-ax(CEzff7Cq8ue`n{ujMu5(FK|X$WmfDVfHa}N%TL*PL^6*0M&*npit*p@L>Zl6O zE^{p_6Y(O_xr;m5i1f@X$|WAJb0aFC%od$kU5#96aVe3L6ve=#YOrwebi`cW=6Ndi7_!1dID8h^ z*DONpSbXxCBzx8PEv{9%j8@ob#g6p4A{v%Oe;7f~1mLvoz*mUWW_CK^WzkjpQi#@gCH|1*;h5%^{5AS+J3!P`s2 zLCyPg=fdarhQM{NOESN5Q9v<-G~LHNq|h-A5RA%mdjPX-i39nZKH&sm{kY@(_MdMw)*R`EB6^!7?pv&~%D(3NXn#Ob zAo^l0WtLLwB-aF+7%~rRHhB(WhZ8;Ct9ED*Xpmv${jAmq1+@N`e|JIyH*J*bjg2~i zf0gNZ={na2$@g@xPHMumU9p0ma=4IWKG)L|DT3 zokz2(au0$KD!X=Xh)b$MRE}*eg37$oiHocnnG?-ZxYs4wT4fJ`a+@6IH+!yGIkNCX z^J!K#4{Ga4=W+WUzyQd0fR)^%+T@~Bf!jm*`hqZOiAz;)Om>yYU!3wV|Gx4(4+(O2 zHd5$%%y>h8-n?|W?9XEtvhOjFXmG~SG_l0$4A}^2&e1R75dZy~OrfDbg{Vr;-B~M$Q`oG0#@SZqJ(MJiy1g#-Q+b|!FL1T+WvkSU($R&QTDv~&zSpn&=b?z@lGgn7 zv831NCUPyGT4ang?s`3ep>m4u-Ij%IY&yZJ7z7*DRd*a^az`VUN#h$H%j2*3B%3B2 z${M7~+lcG?nWL|cyZZ00RO~?DHUYQSD(cpYrt0pqvg$?(VX7)|)d3+^AGn;MLI6}omDLAR?7=jghr8h+>(blTKHUeHE? zPeBcrc<^lQ$k8)iBRu}WK#GQB7(Vi z4cT_~3?&h)58EyrxO`H>XP@m0dRh#oN28qJmW~Wr>jm_@g;`#`b%=M zO$RI%2iuygW7C&0_pco+eB{e1pXNSqVsQ1y5H{&HfBw>5jOA==ogOurPIVF1a$bw% zO=EDE+c7yHOca)ke6BwUvwaurk|PN>PikVj*C(K#ZdG^XrS}h0)Y3u%^+VBGOHy}7 zZ}g-EL1U&7Jh$vGQ0Lk*_?BGDJW?e+BIni8T*aE_t}MHmVe&N1I=!3$%Ii5=a*9yW zXI?CY80i77{%{EFs}&lP3A6CG8?yClMGX%vuj2=NY|3u9=0%iaf!}s?^$r(=(!2iV ziCQB#-0!;OnzJb8O{%I0I?vqnrEKaDcB`&XxCMMFttT%=QHu;%Dfpf7>{eR5F#6~0 zBUjAy$_hp3WuNUg4zth#LS|y_19sIMl0o4LqTSD5B_?4UKZ}pIPAWalsYEs7id?SN z*mONT5i@8N6(h71SKZ!nTA{{B*6D`I%olI3_kJEn^JzRelx%G|VdNl%%}Ni##=Ly> z%nvl@<7=dtEW&S|UT|vXUvZ4yX79{9^3Gf#apK|WdCzViczjIkjA+u`Q~;kV$e=U!PdruerK z(v-UuV%k_fVIu9Akjog2(;6At2bH27f}U^u=T^HWg%+VYx5dwdCD-18QMw=!^}B0) zft?ohD({el9pT5Cj_X!A{PIQSWP6wNE*kqSf8$mM_U2=`jSLe*3znVv1RAN5U<>NiuNFGsM0$!)L5_~b)=THsQYNQekzWl~dRYowwcZS{)FCZ%-|Nb9=d$(qY%Smug?l-*d7)%n zT>IIV!_p8OVJU>4%Do5HrXQjkHU`oK1vyn~Z^dfGRMw_o#`}S!gA2*u3y<^8*IyaG zrG*(aJZdMY>PIkjUv^KMvbXl^A*#D%U1m0XuFQ&8QX?rQlymE+dRxiA(5$P1;GE?R z&9Lh}w;~?O^!#9c@y{JjO1+h6{D`0Dw5sdAQr3cRDjhe1y?TG&9YQ z2quorcO{SFHp?!y{@y6srt})Y5kedop37FQPetfi&_l4r-}g^VL`1S}6=mu|_3f?0 z5myeEsIkz_ybd7+CB*?;1-WP()>MtR&j5WGpB&9$gMr9p3ugPk?b~k=9EB~O&b@*2 zVIVhT=QbAOsk-2MhqT-Gy_A8+E;8v?!v~!%nS=MD^SchjZ>*_QW38J=KZN4m7NZVm z&n>y`Y*#hvs4BGGkgrycSZj@H&L5d@39YJrWh|-MTy1I>kA8TSp1)t9{^Oi7ZmyoN zn9pLj!U=s?6++1+?wiqZ80DaudFS?Bu1rEVI1hcfIAZXi!>JJDg`cp>J=wvxA6sRs z;_JNnt+3*OfV01J(dP8Nl}@JK*=yk2rO>QkBY^-zg;>e@PT&$GJf)h$mD8nums*JT z+>#e{zCBX#s&(l>Tg1xa)d?K5(g75T9#xoXy!$n0^V^dMJ3P1VI@>btQc5D(ulv({;l&TN?jYGRY~tZL;nB|9XLxHY{@uv z>B@wo;uz1?VCEh6DZ<@0iZaNcmp(Z0Y|=Jeod%;{RBI#DKNu7YDGAxA;m@rHnLRmk zF1wLQ$` z7k*DQj2)SaS>003x61LM&LY?7c0wLt2nF6CW&a}S38wM8*5z@Q9XF7Bd`r8k;Mcc_ zx-yq*qQBpdrSfBT(8UqigraB8Xkady)qyd^rVU-X#^9oT_f)d6Tz-`soIjGvnq;Tt z`*bl^XT<0%s}bJnlc0|3RsOWsM!o(&wFA;c;up^2u>!@RdXXp?O`)EbUTN!{Fbs!x7JHB-anmra;S#?Dd(T- zJ;v~nj5+&J-N&R3yN2>>`TJAV)-}HO<+AFww=B6vy!i4wy*&}-SJ!sxk(%WLPS8k& zXDQJc8;70Iu6D0`7X9wm@iFgTV=74PV?^E|>DLJkN)w++iRC?_uJ8R;g-S27qdF^? zm0&;^zv@5qmn>;851%ol8@`TNa$B`I7b9`h@Wrm#$hXb2mxlgdK}%M$Gug^Y#m1^`7yfYjLe(3OCwBq^(jw^{d3V-(4VA~$w*L-+~a-fwbJAoie|ct_NrNJ7l_zBRbY>I zM+KY!K36x2u&NX?hVJm3GGm4P;Alb(GDq}0>y zCwg_JevHew+U>F{q(6-e$@2T^ zZZ%#+J^ZsGA2aY?x5N4v)y`0Et^kUHsbFe$Mt0-}#79N>t<$VL@s;qD4c(0>b?DNE zU5vopwhb!l3BTWRe_Qmq<{ZCnGx;hyqxR4uEh;)A@>zVhtUGe!gZ%R;+V4m1n>I~~ zGoHZwVUUEEyrC%&&+hsgr_OTZ$nl&sP?lNseO^`Z`P14ajnf-ZK08opY7A>_b;~g; zI>|zUslfdZ3lxhpJot_G)Dbm-jImFE?;#~ii&Z`I8)klb4LHIN1 ziPzl10#dNm^*0_I?l>Yle=~JrD|c6#asp?YT^zb9sMo2x4 z9jH7I4*06`&M3j-b9wooJG>lDYdHWQiEUx2+b68=_I+gemWP3=(&G?X3+?v&9`Riv z2E5^~hW8RNuQ41zdqGpYfbc(|`+vgU_4S;~4&!_;P>2+Op#A4OfFURdzl`F)2Vx)) z&H8&#;rtD9183vp{}uq8%_}sU&exwU)fgNbQ=uComo=T?22P{0EgaZ5JJ<975|{+K z^RG<-0F3}W)%o{v0A89?Dj*V=1z^^s0kly2Aou!C-wE^qD6&DMoa*Ta@(?X10ewNWQ$gU zp1s{fn&$MkhvS7mfD4;o#G1o30Od(Jfk)-Bw|hWpO#b<6bbBDwE;;u0Oa92o*bXx3 z*4^mfQJ5oveaG0~=KH9`1>P=^LZdIyOgZ`a;$xH3S4T^-yNIM)j#-1-sbko@gGZ== zw+tBP8gip1zA>yBfs2u%eX1|`iee|n+&Anq#NJ%V*o$AQ9@y3dXG6ldBaIuOA7%;! z*|fc(L`|ek{2%S_DYS!@Z9W3`;EHCV{P%%Pqrw>tCEW6F36ne;RSV87^vd{=0yQCBz^OOl~N z8uMF_mn-9Y;EJqw8#Kj}IK%3Dz}2|N?)dwcQFHt+kk-T$(C=WCe}?_=FsX9B_(`9z zpMAz7E<9V50IGzeT^FKUO6>++?086|yqumG$VgCa1nWGXvB7M~}zDeY|{(Nag);oY`zq!+2-N}g&sE{omL;g%P%!$_TEL!vRlU42(TkQHW z0Fhy$vbT8ou)dA@?^fk)7yc}mRPXZn> VQHDX_E8Bm7LsATo5D?b$`ycOp>b(E} literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/E2-fig-pet-model.png b/docs/source/tutorials/figures/E2-fig-pet-model.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c377c08a0ba3199cca4fb3610aa0ad08ce41fb GIT binary patch literal 57162 zcmbrl1yEc~_cs_LcyKa!aF+oB1bwgpf&~r1VQ_bsBsdK25(uurHCV8j;1+`G1a}>r zy?NiieOq6BTf1Au6m`4$p6=7fPycSjI~6%xEOM+zj~?MF$jhiddh`SW{4g<|10(-T zo=gG%9=oc`Nj<6@q1*-@o>@vNOFnv36N`Oof(ATeI>~=*~YUoLyU6r#$(nX@Z%Q)j|$DpH=eI^^v)h=C<>GZPupTohL@H`)*UVu(;Y3yKfc2F4E(Lo zLS^uuN#Z}F{RbZYuOX?AFaqFN5Ok#XsI@^n*rd#y+JtGr`XGKHi9Nn)5l0it z`(|OO0bHLeK7W1f2H3butrktpI>gl1!4IiH9u(ZMN!Xwl#;03go6lA{hI|z-;sDDF1$7 zc6p;Ay#;UDEIuD?DBI5Kgy(iFkUbHFgcKcJj9hP}0g&1>xIeB}$w&DQ>3Vnup0u`< z%4etZVA`IOh2D-t2I~k;K4~lJL|(|ABE!WxUHn;LM(E^>kEH2F&zNkFbtvBY2lB8P z;sB}Bv?Op|F+)ObX_32vx=W&LbXabANx?=okJN+NpU6NOg$cqzB6|KJ3yZUiJkcgO7oo~Y7Q$(%EJ51)_X+;`d2%L72 zBL4{k`eNU{?MtVNUkX`5&RCZA+&%Y2^!j2!ar&<)nVexiLCLS|mj7|1u70^XHDs*0 z2wGn~7&lJ?U)#DlEK_rLo|H*dwaq=Q^4$B3Cr?keTdbhKQCBL0< z%x~x@t>hUrN+@x}$0OJ3+Vm()+Z&UWN_(eae343z z2)sg)9>@L7E&hA{wX63i+e& zMnUWJTPKhqY824OK7PDZZZf2`g1#GdYQhtU~%eIo{wLp90$@q-MnC@G}MjHV^;sPkp^C~k>S zj8>0MH<{NorD)B_tT8T}L(g~mx325a$aO?RVqY3c>!i%=;u>5X%?n~x)!Rg6vmesR z0^BPnpjGxDa9bc01^A>Bvu#%?jHp%Rm85iIoK?aq^_qH>~2{q!AwC&|O>1u_NFfA9tk(L*7*9+_M>Gd8xT!D92pGSzf-t zUJ7NL#@Fd+c_hfkmVz*RKy&=y5*^&fp5`NamzlRS(6>0;2~AAB79(WfWcNY$dA-*0 zbYq{VOZ#q>-<~{w?5J)A8u+Y=T}eNa$?Evy;BKYQ&fI&V#| zP%cscc^gN)7CBh_&7{GW*<)`;t>{aub1yiOourt56$jq=3qM-iAU2$h#uHOYJ1{uZ z0{8eJM_gapk^I*%XdT&AraBfU#?nX~o5))OnTbQXtgJyeVk z%qQA@;d1jAy@%6;vgF%ldpC`5P{B8Z7EAnjHMP1W<=_*&`TQYJLwazX?rR9IzQGX} zwJ!>rDI z2%f^Q7{4rv8-^iHqdwIaQ@10EiB1-FB0Bs$()oDWKRT}^DTDf0U}`7#_g1qWgk00S zC8gd_HyUi=RI+@PsDmhq{CXL$R{cH&Jxec$<$KP}qzwEgh;onSEy9mHAH);P))9;g z%R!&GoeoWA$z1p8@j;}~;eY17S5L0)-an$X^Wx^j8cDTx>K?)FntE+!4R$)l;2upL zP?Gb~Ax0UlVMUVoAT-5PDl7Oemz{si5-~gP4fsDRU97gCUt6V`$!>@3iet*FN6JBD z*xNn%y9r%GYDIfx2M6;A(%Ax)(-TaetU7Ir+Bw|Ni+(fxkY00?DOC0v+OI{h(yHQFqm1wshF1L1Sc2VZf-eHF#Pa z^MSjVpOC_b|MQ1B@tH)9UKtiQqmP0uojD%{SB10|9Y;TcpFoqMHRyAG(EERTr?>IB zC|WJ6$8l?+`7t^FPO$fjbUR#C*{5;QH`<9~ zcXc$?-PfWq`yW0BQ0e8L#|4E$*R4_2))P%zXGw3!)5Kz8j9y4ReCny*(odMUNn$@( z)v_}bqRw%*3W1C&e?H$I-a@Gp(Sl=ahjiV$f`dLu^(4Q@vAwDBl5%wOD zPjz^!#dPa;qexV&BX_G5z|_Alt=}1)(TGqbLIPq^X=-|r51Cl(GzYGukzMEeMB}9` zWT=h}uj|vk>W)kX{>bekp>|@UhMHcYoDoDsm=rQ~3#~k-6CwB%0X<0?-#Q+kul8Fr zP!e4k6|}+p)Kqg*WxchyO~&tifvzKBFS)!)ev$*7RDB3(T4U7?6}zJe>BF8h(FJWV8tp3EJ#`W&McS89lm1$9Cpxco8FyhGh`YWt(DQb-gao&KR=$SJObF z*gAY0_WaO&v(4qzp}GDFFCogsj~{ZHR$UXw&zFL%uDmC1t9_;L{Dd8-USx|!eThQP zMe>cV`IftNi1yo~Go5*(t7fFL+Fsd4%-?^SgEZcinJMnjRpNL9-ghSgScUAKAM)tx!ErONz3 z2^X`E3H_4#qprw#bFT+9HiWaG3WI;Zv@lUz29fxhC~U&L>?`?f6!l7C!L?r29F4P! z-6S`e&0hBmjT~fAo;kHLbsl11WSnDRafGPo%&FL1U>i=%Nv65BP~(L^r3G%r>Yc=( zPpTQg&GA0+8~DWRL(q>TCs%6W!1oU76MRpP-V6SQo;iGzw#KA2te%&^q|#Z^sC#*| z8eS;0g8yv!X1c~(%97u*4xM^CRN}yC;}tsrb(6!|)iTk3v=#~9>U+OET^{|EL4%#Jy z4O`wTSsZ1&!oq7OJcWudIR{v<*IG!a6@o0w1)3BaC-!t~C%s0fj0Z2h`GU{V%7cO3 zFm^|9AEDY#)MR`Sm%`49|uE*RdY^YrQD zs=AJBeQ5iXfq52|J%k8R$^#%6Py`bJIbDQ{Y53Fp*`_}@Ytau7c zrZ-K)EzEM*ZkMwy73`w3f45P2}_r26WF;0rFL)ZO8v5bu-2Qf1DIM3!f|V+gtKU7>X*6Z=dW6e#{&g} zKMCl_i}^8quSL5zU*35Qx}8LUG6W#C9~*A>h6dm)+dCX>L+NpV8bxKEE(Mz>;vKd6 zUYUhxj=JkK*R{24PJ?9kwqxZebnMn64qj8s_YzF%r zmil8=GlfkgbbqO_Kk>EdFJfx+LZ4KTWefOqtC1k9QNKI!G{?!}ZSH}=c#8&e+uah5 zPMsg|5|0z4`-IGo$DG+gCSt*FN&pfzen?Qc>f^v`mqgB0v?VQlWk@=RN?DB=n_)0W z|MZfLEFWtC2mZUmuK#nWmBeD@b#az%jAC@OWZJC{ujz`DvA~j}iT2GN=`4woo#m&Z z{rj+kfgJN#)uSbmFXJ_nH)$@ST0(}QNa%cbo208>4Xfs*ui0An847&)&u1qk(h=nV zYEtDKgh&osPAp&hp=Z~;qbIy|QYHEITE8543w%)LcM(Qj1zznHYI{INvw5SH$!ow_ z{@l}mxY9Co8*E-&$i2@lEfRrh5+31+TU}y2rz+h}=cAB&E*8|G_mqH&%An2^Njq58 z<0Tn`3l|+eiGr*YNOFjlikw-(got_?q*ZG@wzeJ8>W4%4w$~AZh1uYNplJyj=Y4)l zD~o0AYbqwFUJlbjkS<;Yj<$_n`JKV$8k{@J+I9@1y>VbZ%B5dQV1-EFX~TA^&L~BW z%pOhmoT#EGP|w(TtaOAW8|JH17~w^b=kL*j&XkPoaEY(JX{y_`;gmhN)jC`J(%^Bt z#rz#I^$S-G=dkcWIv?R$@w9rsQccBW;lGU zp{1GaY~q(4thu~%w%0H-!u2G#MwmL4+#TIFFej!)<0Z5woeH!Br?kid3#$cf z$A#F#EpdmB_q^ucsyeN`{eH)8xVba4b=SE%LjEh5547lxr84L{+T1z&eU!o_unJR1 ztLNrKeH_GSkP};D`?*XYlI^e5*mj<2>neBu*(Ykw#GUkl8BWFuz6rXgV((>gT2DMe zg4u=o*>a>k;U)YoVm|yfp99csoahTNXMUHnW=Jf)*q@uq+cc8dOyAT}+|bS&+qSIV zJdJ8p^k`51o~H^;$|n09B+(Wj*L+$X!LAy}gO>S)ZR4P19-8D7z?+Sns|h{iQ1f|s zW_MqP$zgbhnVRfd2uQQI$L7`UYlrY`3TV>WXETol=?w1>!<}Crp&---z2D97km|I8 zh%-B6_O@gUuv$}KefKS^ZJG1;mlvb(LDFTjEqxps}U!&#N zN2qFhOPAeMLnfhT=Og6mf6(|HU_!D7*QCm`u~H_%C&$LJo|VT|uu;Lj61O^-+k6!3 z;`~>F<#+sj>^-O+jeA2te39@dK3q?&EpP(bfn2BMjON*kG#5$H)y&chWbLZI8R_?q zF*Kss=P6{A0!bHHSn!{Yuf^9YTaI7qU6C=EA~fF>(cIsM`@S`cp8m!Wd`J-)yCIw` zA!~tVa)rPh{|ZL^dTBT~nHdRZnX<*!re+_deJ59x2AEVm)*^XB?-6-%`5)xj&&Ep+ z$Fd_wWsN5ff!|#^CqunZRbfoYM!jR@;I(8NgaO~tab5I)lI-LKs1acVu6w^vnP1_g zqq-d|$C>>PYI&a^EhX%TqBCD_o+~XtxXe^UKL|W0aS1-~;TU(m|58>56YqCtDA^O$1fygRDZ)wZ zIIc6l9KCEwAADl(^n;76)(KDOdT>~USN~!d9(IdUU(D01`*R#PBsPje0lC(GkI1D| zn`i>h`~|VC4{5H^z2%dYnkN$^Z z1)cyqqcmF*NhC6?ioM-Y{IdrN0kzoha<~<*xUPJeqOD`ZLgIVfv?7i~9Gy2}5Fj(~ zmM7($>Y7~kos zenA?Vn#7JRjKlDYLGH^UCg_ z2JB!$^L+))CAIj&KGqt8T_k8i5W@KQve=fWP3RQzZPCLW42i)Onc_(z4Ox7e!$tAd zR*d}jNjkWeUgK>WzOFNsg!~RgK$E{ypr`P1t}bOm{=eq^jX35_(kO{eh5{ z2I+9iE^hymEI&s7so^oJjOG-1zNpvzBvmwpN3VV^MH=gItud@)Nvli$86{|7bgSA< zf=Ym-sNbT;VfBg5app*wi$0e=spqPA&s*d}DKmHvldm$KEDDl8fEX;SH z_J^zVi&e>xPD#Q_PKrncboTQh#_XQ0M*XM1+eqdD>d-n!$eaB{bx?048fMm7a%Yf6 z+x-U{%a;KI@wH2=B++VbmGDKSH1#~b*5V*QA;^pMh;_IX!a}Gpit2r<4IiYXSnjJ< zB6oE|<8gUCcG^q_5z2q6`-!x*+>t-Kt4^CJHdBh{aQ=7jK=5?P-Ha{G$eqVvwA!TM zJR1Yvpp@X6#t29&TZzEi3WHiu!@zQja$%ndt-+y+Izouq?UU7ZkCX8 zB%M&n$yitDCKGOVmf{r3j$O0oPphFy7pk-5qW@Y{ELEu2mYnnFQL1*hQI^U#L&fsR1o24->jM&kXG7J2w|DlL^-p zt0h}@I`#)US9)jP>CvreSA5bO+=Me~YnK8?n2?AYbR){@y6?B{>9b#gkZqwiF^s1! z5_ukp&f4JidVJ@u7c&CNI@fL1=rD2Oyt8%H?rqk6Z|SM8CKPTItsr(mN5l@}`E$-$1Ro}Yj0k_+&K_0+&8NzX-#Wsp?DdXa7S;a2%T(>gn}q7C z=L3YxYcQ(Wy5kb*UD^YVdvnuY}e&rL{w0;Jh+$LWq6e=7Qsoy_%}(B?$@##pU&Y z_o}O{?a86V6O=sVPf;Q~f#hNV5_p?8p3WYFqoCVGIj^P9d`jFgKT0hkH=OFGdNZ7}(!1|{7Dx?wC`{FKfBh^r-TApycguWw|*E>O5oUX=HlsvdvWjRXy1U2)TSz=x)>$^cdxB!LK9^ntFi=>^L>(IR$u zo-FPJ|XBOE1v-sK^OEtL2EnNVYfmJLA?rQpOIT zuxXi|BkLT;@yz!| zXFJE@hTaQ=DTiD^z7}PX2(rm`dUQ{#n!K+0ZY^FK zHE>~>uf|OA`;F=Tlv^=d%6odvCHk#i$3nKy=i3hiRZ%y@yZ;FzeBu;?-x;V8PG+Y zA*B)AFh1+ls6O~4ktY)y0nuDw+^e}mS4743;CB%xm(qkfK9B@{na9d3!5E*`E+z*O zYB~>805SJ)TdAq3#p5TjDv;DhN8^>luocSmZ=Y5llf~fqVr@h(_3*NC)#g3cJOICS z?MZOpY*{WvoAVRJr|Fy_UEG)nFTnUi|L4}v?}*ql$g-0xO54kKh)c-3LZ*q-{%E90 z<9NQY-0Kw*HvZYc3UxAnxfdo;y)-~RpAy}}oD+kv5L`EWPsTOmooTdGAlZXB-Z&CF zD%ofnN!qcEcK)K5+yG8C|NVptqPrSURMxp`wlF75u$b+O#qBSQCBbz|g1q*F#fDXN z%dRtu3qj9z!$y&XF-FD<3EyV?jk!}|u5cC+2f>MB2SBOGoCW`BIs0@YD$U8TUB3^= zU-Dn!%Q1UO&I>+YLrIT>4^<9wGoy25sri-BTB;8Z8IL!kW!v5G3I{CUN!)%XzuA8p zul7Jw&}Bjl$N2D)=lE)qXH{x=L>{>Ox@Ko&!jEanS|yCrJT47krKfVP$V}rS3!vtz z_B>|KnJ`qqT*X`YL#B5##Ic@R|4ZrFf;)Wp<~4_96}x%=is$rGPx>VIt@*f<=dsjB zbyfZ70r}vjOrpwVOi44`XtQ*)BTW2saXrbFaIdY$H}ly?5n9W?ekOwsp1$n-qr0T2 zKgS2T)=&oWa%Y-rv3pX|UrPp>pB9d6btJwCE?LiGeVc0we&OgYgNXUObO1XzQb@ePC3!wIjox>IAhPdkm1~Hm`3SsB?8q4~DN?0GP>B(3$^n+dG9u~XhVkS! zWEq$F;Rj2}@g$fG)(hN83azDb9U@V!Q=Vg)pqA3J{k-Rt|a297eQeYPWHdix2{lB`}W6@B``2qK5=Z|G3)&1 zSRRStgA1hvmwssH`)_?liW|_iIPPQTWpAN9JyfoXG$|SVzOg1e++{Mt5o`i1~dA6+aIMR%TQxy403ubCalPxy3 z(gmH(9?xCW)|+)4Q)REqfjFMBTz(a2L(3XFmq53}6DC6+Kv-92dN^O|F>FV;(cc zKfT!RRYAN=@s8F{O!01lH^8jW-t3XtVfj652;H{sRmf{Wn~F_F0d~l*kDxMMY~GM^ zW*jmfdHxs4zsHbDzo-D11P-|hJz1ot^{|!-i}lT>+sO= z`mlbo{8~eL8+`d|E&Fy^m$z>f@l&bTZDeqi)6vMfwTRR|`a~C$n(2bVJz$f$wS=}RNh^D&4Kz&o<}U!&%BIX{4uj;$)N7v+aYK74V3b#Kl`VxZk4=2 zq+-jVwIoyLBQq%v(X~3HTTyS83;?W&d!JQ2E=&;mSkEbmGkB1&?k_lJW^;6iZBVYj zk8V-w{|Gz^*6r=3X=X>&gNrI8;&Vc~1l4-dx(nk#6N!y+3%N?BPpkqLlEIK-5cu+Y9u z69#}#4X>aK{s0b2-E8cuq~Cmx56ngyxK0M~S>Ocjt@TBPV3_Ox=%`Fsn2?{2ewgWFibkK>Ip{QxD!G z(i4hHME5#B25ee=0iy~$`J+H9mB#x&m(MFGcs44AqFg>$`0lP4{u}lkZgq39e|s$E zdqGV1zY=8}`67a7dgIu39Ex8`rBPs?qm{=G8QR};X}P&ofh92hy#&FtT=tF8oY5vhA|@q#x-zww zz@1$yXuAv;CR*8TY z60G|dhbHxs@{LQdqwSJE%78Xc*!?xct~?$=6POkFt+==tpAi7Y{MSsk!=*2dwigGB z>@u3gmGJQ6LGI3@sxPA6wE)Hco;QDaeSNY&1dSC7U0BekEfYQmL%O=U{JK%}v7(=c zl;*5v|9hwPxbtK=4SaPL!-RA@YBbPZ;|KMdCneIl@l;`*=|CMw&e(-8s zVqy>}r|!`{EGH)iUn};SJfF{U?A zX%(1_iwlw|V1MZU?)&4UCDW zm%{?&^*?87E-WryU91CCH>Sa5>=`@|Fc@52UHwl!BswljX?`<}@PFu9=)mPM^6J8T zwL3(rz`?2;1inTcj^Pf?csPEZyR-)U z=g3Hm#3*pku!s8_Ko{UI{!`rmxzN^{^gQpd-(GBO!Y>uc;Drp~fHitY+}8(4Xy1ZF z{&N=&a?8EjUy0=V6$$8`QCOSn-MJLlq{!JuE9L>+-ZlmS%P>HrV+;EcltERl@pU z>Z$#}N>@;b{M~px*wk%rCSGE5d$JgC3>E(tEdaF4_`FV3(?<8Zs9Ka>ITsh&JJL7O zFObFvqxdfdG^)w0D#T3qCio)+U}_c?Ow`_g2-4EiX@!JzfJ6LmgJQit+wN&%-kq*` zNtYo>0S^azpP1dZxo(b-&;^4{3E?I61v_V>`X64H<+8S&Ot^$ty=f_3U%w*rma5On zO4`d9OdK4rv&)aF z5&`n|o!R+qmu%ZO_ge2VkXWPoShfL7dNzu%4m{<)#2R;55Li-A3e(5M&s!I& zYN=$w>-^B5_uJ%3OV&HdH4UG0bAu+8c)iAx9(e5{%8q0m)3630R(@(nysm(U1V&RW zbF`C+pQk#0Wf6pMi{H29>F;d>I;^S5zTvY@e#5sBmnWLam!ACQja_G6+p9X8r*3v* zhO#YbHFftMsd;U+HKvfah8ByS#rT|IWRl)jN$SgBxQlw`X;B!Vx ztE=K6Rg|}|5k@bi={Ytq9ZdVT1kk-DAK%j9zJGn)uT!qJ5i4omVv~(vZa*+J9kass2DN-p8KM9Qk_Zh zKyyWFF3V^**WpGAMSiMYX90_4k56*TUDKC5{h`YReIEriE&*cehj}#FmYH{JQ%0k# z1AU<T!9xfBn5VWN*?L01|5+dUN4ton>7ANGXZ6kn+R)GbK}U`j2H*&L z>Q7Ge0<{(cx4X}XZc!=c9z~%^nd-`t@bED~z+WQg^Fz52>>eyaB zij)(G3iL9sqZ*^tjE!Ff-fs+N(zCNG0*3ziPc%X1V&93(Omy&2`~^URqSxZY8Vhg~ z;_0t#NtZ*1(!kQ;R@C+s^pMePu`AR}hkq-uGFm@He(PI>F^;N`F;OGGV>I1HyZ+sA zIhu8frvk&;)X)j-RH0n&Ea(?w3ZECXev8~B|D*}Dw6u8b)gUefdZ(Lq3P_Z5v7v52 z`f)F|MLT{O*9JZj+5eW-MSMs?FN3M<0=Vgp$0aKJa}Cmxl2gyDrCh7i-A(JzF{R$_ zEw-jQ@_qL_ zz`++S9{U;H7_8;?^NlR5Mq`LN_P<9!MSbo0d-w8$9-PX{F?;0BH>H5HSeKxQO{(zGGpmN7H+i_$}oN^B~FM z`vujkXFyWnTN8zfx4!MyJLUYp>>1?eKsBY;c2gEiHPM=w z!`(`8wXE065BJPT00v)kv`9G@+dLjS<6knm_=;~059OMa)y9mCZ%rQiEv1jY)%rWHChp94ETJw?YNkQ(?K zlT3kp)9YULPv|kz`l!SM zG2NWpG(0>v)`xKJQ$iJHg9*hywIOpDiz|)W0xGehKiNm}@9QRjsQX>YNR0IwC}Xq1 zy4^B=lZ#&#<9V`2DAdb)S*y(X!ND+CzJ7PG)gq8)ZDDyI41bjj3J!M|3j>>O38zMm zz4#m7o!#9FtxJW2fy`R=?2VqH5nNvU=AgW)gOD!xZw80|T*XA?F%T2Itxc!>0U>gY zZC;CC^FqkT$b=25BF0`M2ta^%Cyy!rM=MS?GmS8q4cLm?CqLOOAc4muSj^=H@?s%p zx`(CjI;)xgn$K^L^Xk{8N}I?Y9T&Y=&V>PeeUKks4U=-lmN_2SpPb&{08`Eiofq0g3qr=?NqPhtLFzn1m!3*kl{n$=R78 z@4M_WJe*G02^>Zy6fWDWaC9Dl~@K1=|(KelJjpPyKK^*-JB zIWRz&_Z@)`BhY)6YS5D(D;~MGXGi;1{&6CJwJR*l6J#e;NF5kpC+vuC(9nMe>t2vD zEOZA&(qkBaEk`JqaFj9yl*6~srFkGYjsAqKF<(SH0rkcL)U!~oKW>W%QT~e0DEzmQ zia4WgB964InF|Iz9XB`LH{FJ{=pR635nK|$LktD-HSoRglJ_PRVAhWnDCpgbcT?|C zIa|1q0H3v|T8FPE7+#DwIWcV!17D^DV@UqW0cw|1rmuQU4pK6Kphz$q2S@Lus>HBS zRAy!-J|oWG&Ok^XKMcalu?@wN04%~PsM4VI|i+VKp<6r04O#8@SpxfZ~7A;Q^z25{{fx|C((AfxO{@N4;G>zj=1N>v~RGo+`dd;N)*yQEqV3JMA-2>|m$&1`K4 zjYe&&+9B*KijR09uh|H0o=c$d9bntv-^ygYWeMh>$L$gysWucNGstQD=V?^&(Q&se z#vq|@doDXozzt+IS=)ZxbzQ6=oLag}q4tOSWwXgsejZ=Ko>*FWb!f z7l}CyyMD3nEE8+J=Q?n>r^;;mbr}E3`op-$SUCZTipMbwvvCKnxYQIjGbhU^%h<+$ zT(9t#TgUcu(!d@G*A3XeR|O5Ga&J~yAFXr&^^_)qJq$?H!%xH4l5?_|Wy*`W;6J^` zMS#25Gnh!)^mxKetzI7TbF1#Ib41HA#rJwYyiV^pFt1Smh>4r6D}OccygWJbE~DsJ zsVyv1Z8}~pj!On3&jBbIPXup(a{g;`vrhO9jWj<56BE;Frka+6laqkPs7ZMgbMcim zwBW$af0!cwMrW*L2;{EoX0!k*WbB?_XH%II?%@+|wRuzgD;QtMu%Smb^-*yDNjw9) z1lQ_4HICmWU%bJQG+UZaKdP-{7&hN~`D+#SOy510nmIDmCC=iWUkU#5^0RqzEKw5a z)0eSFC;FvBZoy%)&WDVZUv+Xlm8Ot?2HpleP@!juITIo(7v$c#PiuUuB{)8MVK-_B zch7moz}iPopO?HOLT(b#BK3iKEpOd?JX|Tcvq(t+{K=`=jas1Tjv!mRrb6ih#?g@^ z59-5!DfLSCwxSbGVos(;kzhbz>dg)RZWtBjK$V6v5MrL?vO;1g`zhiI6;rVYdVb(X z6F`5)(cZe>olhG95|Q}{nkvcozvHWwV{shNH%$IHJOumf@WZyQ*r;p#o)|Fc^=LRh z9fA9oD{S4*;^~<9QzI@oBs*iijr;tR?5#Pe_nqP2)^qb2pu`=bmP2r(=RW)}(Q)Ha z*!CYFK^?IPa8t&P3fD{JZ!&dVUs#;^mSR3goAEkMp%J}!j`f_2N__ePdK|p8b*V|u ze{Ug37jjx4eu-{C<4tOCje`guhk_HV|4e)B6L@5YZXHc>imT~OA$7Pkde5h}9y~11 zJ~UH=#Zvu9__RNsXJAy}^j1SZP&x9r8m=02o%b-aoyLFS+IAbxNd2&^sdMF&6jC)GCbUjdX1RO;SN1tWcYbGUDSg-Q}>&K6RP?N(=bzG6)}xtYfA*iIzEp<{9(-> zM<&Y|U-h=8dHu){)c-%?t38Wu=gej%AJlZ(c&Hj}D8zt3?53ci0s-0)#wI48($YY* zHXu+L_`CNhQ=q}$Y*RrY0`RQ3fPc<`qMV`qjE4P>Bc$qmcAx-+gFMRKqsgi7o{1}4 zB7##9zP4D*FY~;aYr{tDHk9J%@6H9uLBbgmpeQ0!IU^t zAn@Pri_!em=_XKSTD?1Qk7g5uSPUD%eZ|Ck5Q|IFi1+g=Y9oF+;>RzpM;9Yc@z`<6 z7!BaTFEjF|Q>=2Q^OOi$Z*t#waz#yVuKMWGs#CsP!5w7sdWgMQ-=LdBXD2KAzyO=c}@UnRTT)4-~ecbDXcf z@H=I&Bq#5Pv3{9I;;a>`82cvjFsJsPI@CH-XyP7kfR*iwsP`7D30wFn`qtIyXLK2X zE$z2_CXqE#IU8BybzV;;7P(rVe>hU{yGtV*%BI9A-#US6P?E0PIW~5ydihuE6N@h2 z+S=i0P$ww$UN~mD;-;Vp-|p!PD5cs(-^aQfj@L75qiYKKrN^#Bw~v)Qc-K9MvJHg%KFgxpH9B2h(F(}n2bt3ydri>-OC#VTGm?PS#!S1fHNE3n{o zzDwf)m4$G^ma8&**o*vSdR*iC1+y7V^0^3c{-i_m8b3#}1B`YGh4&UKA#dR&pLv67 z8o2dpztYaBHW5jLmZl)pp-_CL&TJS+h%zl2rI*&#cJ7r`VU6+D1C40@!&mFphuqc^ z%UL8*8%o8}ZSPFHh*Fg#CUy04rjf^SjMB&si{zdqIvXWmd2(H9!!Khx{no1a>>?AWrNF4PM%}t zb?CRagmkv>xtfLVo&cu>glXx?BIT>8>Yko$Nd!JER5Ra3p<^Tx{+}>UcaEq{daIt7 zR#r>Tq4qYJ9beFCb|bukM*CNnklT1*lS~S_Bwq->6-@o`F5=;Xz{fsYS7)uQ!qQpL zdXMG%K+(RTU$%VCD&qXw2&8)cf$`ztB-mre)J~}GY0rFG4~!4OY{NrUTRnVPk^3f_ z%CVf^?0tKJ!$ahBi?D#tgJUz_X{yun{8p7NYwtrcl%O8UTl(Pe_2Xh2UNa>&^8A9` zQ?Q5fyO1SGtwQzKafx4084#)6C9L6tozO5o*bKN+kO&YB^v5RUz^4nQm4uf-rcD0> z2ibD+9E(0F7M=ZjzDW@L(oX~SR&Y?hsXc9?9hbc3l;0}yedu9W@ohW6pV?#Et3C|Q zHwOVp8WBf&+nBxjMki*3MjY-OC@Wg=}oT51ft)ke}E zWKaawBKRb-(|LVWK_kpqAY-;O^#-WKMZA?2m^no_Qpj#sff?YS#agIv@a1VR9I}E&iO)ci531s@83!>w>igrb~_B4Cm=@NV3`F*!z`F3ul zgDox3`+&PO4&zfK-9NhPSc%-F=o2>GjKDa8n-OX2V zz!xvy`_0AiL8!o^vetK5JDT4BQ1+(8;&`)(+z?4ZaylV5HhgQ>fMiJa$EVx{cc*g) z0KRvNpQ}Gxt=IfW`?jdAj4~BFwa=h=bnHphP=~>iYoZTfPc~1`>?G8=Vq#8;B#8tz zC6?)o8;+Ju;evt3c8ipB;Gm7IJ5 z@@J9hUtw51OS)*wwHd3%{T^)qOU`V9o+nse?tJ3{IrF4Rq?`jEz-R(_Ui%=da3`3Y+D;krQ!PHHJSLz)yWTZPx>L4>X>bcFa93 zq4#=cp5Z4@`EbI-F`WJ5GEw;_~_+QvIR0rqt|1G!;XaN`W z0#_4P%gR6#G$h=F4#2$r$L-Yg)zPXnPysyw8Xy71?Ov|Ey`fV!((cftup8$0tEmdh zD`@R*dx45x7 zt`d}sn!bkKN7SM{n+3DRbgl+@RDDHm5*^PM1y#?T3qsDfK8?>GXr*0Kxn8|=Gt-!S z10CD>7C*D0wS?4={S1I9Zi_7Pj+#!r}H_G2BsEK7GXrmk`e5~P0;>NF>V+*L6y zBd5Oh+g^HfL9#9sdi#$@Pc6nOrYJ7!N1L{W%ej5dy=baL9WVzyQ@h0YwEB?EsL0kB zw8iYtXudR28&;_8|BJA*42Y_0+qNyGbayv0q#~h|ba#y~ba#hJ!ywWr+;lh6p~TSL z2-4EhUEdn-=Xu}v-}gsFahTbA?X|9ToyU1DxgAH$AGd}j7gM@|H^jbG;bl66ftB`M zmL$UF^HS$*uVNm@FqRqDwV>Yny=6_|oaShpHp=fk+%>J90cJ|GSjuhtE3)9mWmY2| z!`Ds7o?p}=H;s+t4~GGY(pG4ZGI8j>t5e&_YwD0?)Qj)3+M z_V!yE44}v%a!I1gq=Oid#bn}ZHx57Cbfn-4(aSc16U{fet(Uogo{?z4Fh7WSknaiJ zC+C*5VO(M(ru7FEK)1z-3mJKNuqNCq0ILM42)gtP4RwJg*5JZ-At9l_{3RNCnDc5k z_N~qg8*dvY70lQ;I?%Qw?-}VoKVT2bStYNDqL-v7d!~eYFc-Na8AM14tYebfXv*vCk3O}`1}<2cvV#vo>d4zz`RR3ma_{i}!(IOFB{}9B zTvqJnuFm!dX@VkR;n=X->x=7?+x>P-@DUlo<20LIsz_s@2|kHf*Uz6RtroSG6KEbD z9-`yrQOOWAbo3S6pEDGeo12@WvBQMMa49;WFgUj1hTKKd%1W((HV9Wu9T?%y{NiQJOn4;w5PXM^yv4% z1*z-%_y1t=dS{!%k#GR?2)q_(68OCBnWBrP0ON4<*xBckQrzy(+9UpL(7DwMk$T8X zk`*0|Q*AZ%x%E#9za5&gDCHMOp(LsU*q(n5Oh^=6#!6M8x)i{XCI?dsMiL+{4*0h~ z3lR<5f=UAD(KXh@e)D3%&w(&03^}aorvaOi1Tl><5Zo}GD331;mYT7^rGr9 zFG+?>RS8!=#wg1#U=*w^q`ZU}Q! zH6GhJBBVGT7KW2K`nDI*{p(j+>nWju`~94p20KcWP*U1m#i=q7wLsf3L6CK^#K$E` zcOn7Qeeuas{l10N)~i3SscG1=t>L##^>7QJ?V4&BgwzWQ&o=E&`?G6=*$QbJz7_Yl&*_ZE;*nddK zrl;gvO0BEEM3fXUz5izCS2-&5)|DXdQ&pW49@X3mN$zzM39XyQcL?Vb+tTNWSFB#U zmKeVl;jatYt{fzHCLyfHUt1odbDXyi@Zaky!8F1;yY+Fqq$%h3Lu`%$;rwlr+O*6>xs^$(o0_$ngl zpEx4RwMcVc%4%=-)H!y&bxXOL(3PPi68ncMuW*k$KZV!D{rC*)4ca~sB6@@9rpo^J zvE-5zm&YJ``Gp@J5Kve&qheb?^Ed4$YI)vzbDDxh?fe*w`<%zH4(8bdyp|LV*Fgin zxexCcz>a8f`K>o|(-dJVG?0{=+v2U(O(c71uh+*>?}}B%r9|k9#V2;|XjtACUzWc$ z*9tA#dd^+xiRcid)ZDKc3Zl`QmeU~E3*RMd`@*J&DeXrC_AEGuo68X-yrL@6&SvZ+ z{t!nOm$mKve(oVD+xkZZVxVHP=pxGLdrrZ%)8> z4O*q0JR!@ac&@xP-}7-w{x#b#M}m~p<-UG-NrBYJIOzJ6Zj(DK)_ID+|ItH)XW}J? z(8mb=Hf#hbB$`?ZAGZ2eJrek<9&raeFutuzv45%^_-$yFPA**J?mDKG7?V;MOkub% zPD$j1cXaa7_qq;Ts{6=GMGvYTbj{B485xY(m00 zt;}A5((_LgbM2?ilZof+_xo?XVvL9sY~iEaD-O=>h(nh|_mU1bKPV!HslqARncasD ziW@*=EgM#2^Yf5@8OUhp$`(d!z^C$=+*?TaYKNOzbmIY7W$La*ydUtXx*FwTl~A-p zBm{^(`v%@Qh zvVg=Qc)5|~t$%%U6UdZd16t3=EuWQz;MlTl!cC?TZTU=&VO(t$OKulC)x3!|ng^+s z?v&Tm{RUUwe~9(u3>_dawGY$x{9d96i4~wKzx29h3hJqSnPeD2dw?^y$IeRbMy6kW zR*5MXlhX<%C#G#vI^QZPJ15--dS*a~Glbw@stlSiQ)PyZE&3BVhh6Nev=a?9CH5yJ z>YdM_2b38RXt}Vw=_rZW=v%)RH$(@k8e46*PQP=;F~g0uyPdPziCkn|@@&y^eynhP zrPega1?%V^eS2*$D9YT^aL-V|Y+uN0DCwO8moh~{*x{1LBpMX`WTy(De%Ne)T!yK5 zc<@Y3P0c5ZiMhDA0`i?9zyP-R<6#R2yKarRt!*h5eRXJdgz`SV-`vdaZdSmufO-IA z_uy)}CanJ{pV61q>m}4SR$Z{Ez0=h|6zui(y|h1NGu=HE&1d1?i4E4`i}c#vp?yi9 zYWpGDXNS}A5)EVe1goOA%PFkMfvg#SstVOf!DI2!Sz63`N$0xgbss*z{Qy4!#roMw zU;6VOEal#QwZVL^|Nepg3bJ%2l-M}+T=z5dd+Neu z=3aWuOG<60LlKqwKou&lIK_x!f`*2+zZ#=>$Zvp&iAl|310NtF z7jO5cTHmbX`Z(TrTh`=9 zj|Luv$3p0H6Nnq!wRzVpOx92v45U^q#~M}oV=Dl z19C1d&1ly&9GkmLQSjgqG!ImrKuy;LI$YE-lRA9l>#joi#S%){`PB%J=Y}6d25?dO zT|@lZd2#TpP{NF8NKSXli)xLh(RNA%=^@PXIdN&yR)R!=EDpA~R6_R=2--9GOy!nm+`s z^>2CGgvgAwco`X&^ld;8y(cGSs}RcBY2BerWGw2)mZ9Rh z5kDi2G-YqEs*QZ+T&%URc+LTf$^kDgAave09Sy#|el|(O&%~<%>o^CM|9OM7PZspA z%t^dsO6M9w1J>_J{{pms^+bC&w{^QxMUfkxurRpYh!TuXvZA8mzkFkCEFE|gMvjR5 z@;bF+1__!?72;Gia>=o32%0?RN4H8s$1q0#Vp;+@_A~!;z~ZBf5Z}68q0i+pHVq=U zf|S-3(`zkG^IX87#alZBCmAUJOuer#guDJ6^}?kIGYjAT4#~!hVx~DpwK_BK+U30s z@?2_rOl|2+)Ce#S?W&-%6}JT+MsXB*>c6_)O>ep6r}=y?r%pQ~y6D{4uh8s-PBK){ zB=Cce_{Y}M{eI;KznA+#l#`wPkHZSWo5t1I`KA_)rWaxXqYEa^&RkaUy)WhZ5cWz6 zz~FH)P&hycVwIlX%U~QGV?E8rq!3Kx#{haJAq^sw8K64(%30^0x1d%P&4%~-xrqva zu}EVZ{2kDF2E-#4pq7V+?{vs@i>kWg|Hea6{*+J7XN|B;Q&3O{iHr>XPeC8>Xho-x znu`l37?V;%s>KB{T>)e5h#253Z)Ghq+ny{@*3v@J)zuYt>rXuDa{egI0M_2v;bZ5U z%xD_CSiFCZMYejlT!pXq#cmNj$DlgdzcW#7j)>^*mlHhbzzu5%D*(Xc^~Q&agUju* zqZ6;g9!7kZo26jN0F_J*@KmBa3?^`=+v)|B2_C;}{j}N*vuf`5zCPKPy)U(DZS~_C zShfMr(-wvJF_6L!G496loeAu9(FeN-dpu=Apfy|mXeb6xc|;Po82}T0&eb}$BZ)eC z!4UjRmtc6*Ca1%42MfQviF_jG+m|YrtLy74_3LT4C1!vD4$R8NB;~r=sTvaBW}X6N zX<$}p0|@U_LZ_spybYczP-O(X0uT;z{RLlX%I(|_e)g6aS2msvyJUML>s=r%+#fLP zod#}3T&Js^HnbP3R(oP@?#hSXZ2tw?lb%0(`n=e2%s3e^Wim2wJNc3?U%s%o*oWu0ro-`mJPxg0F2MZB&Ho(0;NTP<5(&{-;^v< znHW>KiJfS;NHw-6iZlZ+xo&{8-i9r%|Gy}5xAO+_-H|fLBKS_5ztz|+7-S3r`W{CH z9s`P#rn6sO_*;TDvpgBG`RHJWtE^xx`^Bqid>$ttpVS!cjCp0tc*VHS(%nn=?={>9 zBaPKIp3SiKpYP{WKcah#%>k?gT?ad?A53{0nhdXAX;)03geM=vEL1f|+yEU1h>1)(^O1ik=$ zJ}LxaQ35viM`d3eG?p_mFrZm_JzC%9e*2vR$gJDRNr|I*Uf0X**K z`_$>*;NGNfcnfu9+2MyNH2VVaF5e&z{R#90fCOW&j_OY#OBkeuHz7F*4lqll2)?QM#`;jRIY|B}lYq+o$KH*m;pn=5RmDISPPAY3N|pysqA z!{K3cn-QQ-1H?iyo2u)!Sf-b1KjE+4#cjFvzHX$r@T%G_#wdzxN}Z_U+By1?5I#>j zz0Ul?EZxZjtrG2DdN%)0xBP%|liw$|i5qOE=qmiRP+^DvV#cHGg&v{W2gG5As~-wO zFRVkcJUnE+Y@P_p0JQ8y^#ZY-!49UpIf&V8U=$J!dQ_%ma6x>sFiTa-M5rC8&BV;x z!VXBY#?1=$h>r5Fj(P`+j5TXf1DKOxj;^%D{hP{9@z*>m3uU=ei7FM94HETTe6q40 zo-*~alCqi#%7ks5-7vE=OPmi-1x#O{M>$TPbT6dno0$ME41X=}9R*(InlYm(bMMgS zT0piM+w=Q+TwE}B0ZiAzkU8uyoLdo~#2vyfTnvBjEJ-UW!`k~3uW#&b9i&6zao5Ol zncTE|)xjTqxwVx4H2rSCVrM+I{E#{4A~x}u)1O0FEp}n%HxuAg5hIBit5!%a#wG=* zYw{jboM1K{7~F2cm-krEOOi2R-GJdL?8A`WHxZ%Eq$o~U->GZAu2+2i6PnZ2Hykk% zL7!l6c!@gli%fn0l_zG`)7`ZpyVhZika*;OC0K>;s~l?FC(8zXqYnaNpX~hhJ(+T(OW2_JU6)Ul*jM=|vVzIU3yM;JZRN0fz}wlnVA_9PeKCdc5nmV z3lj-AGcY>5OdjSz)^rc0I}AY8j^6LA1N8h&H!6pG8Y{K%R0u_ z??=LQTxV>h?1GU}c}mol0_D`=jZo`zdR{Hzq=FxwZPTN;)+6r<26@y#p{>lCk&ywA zsf>JTqf4+F2hgJ0e4q3%+|J<)-L(=Y5~0tz%c#p%+h$oZHs|Ma6{62so+`4a7@8S= ze?r)(VUs_8Z@UZ=lmjdfpG#-pAYI+kaWT>UM75=;?7)mn!cJ4o=Qdd-plK}^-+L0; z?Dtj~m8*UmyHUX=)aO?qP0H35iN;-1n~`ydUKU^6S7=8HohouxkC>{Qp^!83dWM}$ zOGWi&9IqMpZQ4L!w>gd}T8FJ(gUWL^|M7%ZMtdo`N^G9`4LIDvm!Bq}Q$cl=VRF-C z(z8S(&OY;Pa!Mw!YLh;K3;+*9v<}%*GKc7D_Tq?kLiKk{bF3;T!Y`wD(!Wp4$7xm< zS?)Twq{(OK6?c`k1T3IwjHlZu6ruIUhUrI^niPszfiW33)8ygwSheHuvx-W7o`R(@ zfiV^Di^mc<2wt06CBx>KL)Wd*$h-jafz{RR+FEfAK6sW)8MZD*pbhR1HID`Un$)nS zTkC{Rv+wu1f{r>$-%a&uI9S|2<&U3gr7Bu(v9tDn?{PCDZ1wHOVQNRI1f|LZ5u;#; z`Z&~@oV5THzOjq=eTx3Zz0zDQ5>*(_Oh3iOlwX}}1G0LSj-DzCiXK?N!Mbj0FBwvz zPdBysPt5g$NK934yo#3!mn3`;*KuCSojoeon9&5aOarW)sJ_ z!u`hbyWLNjpZm#}vPvObvA?)-`}HQ^)Vk?12JdR7v&R2U>WReBq*-Hmis;IsDdTPp zzD5c(b^(^rKC9};vAAls`s1#czidC{TiKb3IYKH2Hem)U5@SChsBJB?e)emmT z?v?xY_irT)?)np*LHD^hL2^gnn0nGF4-H)Fn4lzT(=ZV671$;^;mad_Gu$B{IYqN0 z{tP=NZpb!!O;fKVahS3=SagRW=LLRYxxe>x1eM-;|NR)2-(?Iy4G=tQWZi-;guZ!V z0)JW1RwD8Od}(=)`*I5%S%@SO8|9kMR$BnYfe*N8miC9#4Vd3bi>e8Y9-3t4hV)Qh z#@pi=qDYMpS>P~}(8|+Dz>KZIgEnsZ{lop2UX$mi*AQ2ZV0|oJNoJ4OH+E9s-(YmE z@J&%1i^qPw3k(>_ns=tOriw z=9H8E-%nkPRZN(Ars2w-*>cK$r<}T^;GIvmuAK~p^RN{>?g(hRkvg zzW^27CR2>H6SG|}pD&pZM?D95Wj~#+5T#I~8d>K6j0(5DE<@>{j7NJ~#!jXaU%EOU z4qbis*mW@|_;Hf%(^GRV!;q(4B8(Mkg#(jq(IE8al4L3MwgGp2lq+y9f%T6;^@e zS4xMA-buV_1cS6-x3o-p`pSf)_s``;1OJm8JyJSX_Ddz-jN{GNWB0?&Q!p&?Qy~yhhi|DJgHzIk|_&i@a+3kb`FNc z*2AU@BADqY(pReUNqz*s@gN!lYR&KbX&7%yVJboOA2X-#wu6PI1OO*LCw7w~R>tS2 z({O7L_HVZ1=o`SR=g<#L;#N15wd~%8*57~;BMN4^o=e;geGyJb_xtTAq_NmgS4+CU=h88@P%69gtXoB@wi) zRrJ#Dil-DQIaOnm6KE`7X4BQ2NEwD&lztS&LV9kqA1^n9GD@Eqg3sSJ{up5two2m! zT%LGQU~CEbQt~GlEO$=+1Hl8|1O=&ckgD9FUV0xBKk3w#4g zHmeb$jVQL4SXeb^H?rH50pdYkM=LJ>G#OGBr>bjB_(4HBd2A4 zJ9ZMPLk&#no1>r;M;LP%v(WWzHfJ>v!9EjSW!UA%*fIsgC>uiZ_xRwlYO-6mw zZCtH5qaO4m6c1=~%&E$x!j0*+2bGAgqQ9^!&NFs;fR8IJ1 zg5~=$E&28`Z+)%en@d8xl~$GZqE;XTX9EwhG}IW*!^$P;l10^cui!^d=7O?Ks7*+6 zOzObGmy>6@AB8s!KW(^J%37~~`qb~egm(N?)@U$nXcf1yvs9JT=%T^Guz;zTdzYRM zbeJf#yuSNpu$LLPKB6x4``=gJYB%NIbmF$;8o-XK|3%0fSFAyL2a!#AE1(i46T|uj_ly zzY2ZIT7SMWEX}$jREg_V)<~g`Oy@Xc3e$<>23_t zW7|?<)X+Mm4s0og3K<6SQF?3+4J{q>;Tq#29fQEFf+4Fy&`6;#i!1c*mJbu}MA0)} zr<6RUhsjl_L9O^*^^fNzmZSsVPz;{A8OT#^zQ#6QDsnf1oO`o>gAA26*H;w<1Xv!a!HD74KZSWl?gfUzP zKJ22P3iBHfo4)14Z*Oqv=nI1_baXAqeg8C3i>-Ze?fA-|Ef;l#bJ5QZW$y^*mcN(e zqfwW}uoxN1?dN6QvZj;AlJNNtMG8h;TLvl+No<4Qa?2B=>*HP7a_ixHrtAxd@6g|{ zp2F7h%VOF#af2+(&3U5GZ;FpUmZu$ZP}K5>J^WJzjESMs@!=utJ*xvf!T4DNbKm5N^Lr?24> ze_}QTWnr)Zy3%<1TDvs)08!THBfaYjEAQ4HxM5}D(kv9I+JVyPt)Jcv^pU0&B0`iu zZB%g|%x7nzsKRogp4k|vm_{CJX2SxKMrgAyAK3KQ5B<8f@NV6@-$v%W=y1*BIzSP4 zmR>IY5X2gpbw97GM=7hXdH9gh%*aDQe+ zCGC@|#cSg_>uiJ_wtQ;%rsxQ&)PAClxlo)NgDtVb>Jm_Aggjdc`CBzc7=UuagwZ(6 zAXqqdBWrdqK6hJ_nsiWBL^MIVMoQ!IHulliuFnro_fgL}W``&PlZH1!fS>e!Q~X&+ zu*gp_28VVFDFoBuv1pUk51&(l7e>p2i)bd)PyG!M!rjk z|BdEke7o~VFTebQ!~9Q1*DN!kS-BnRQoiYari#7n7U1%&cq$GDHFM)g-}ca9yrn<; zBr7O4aZ*auNqLEB;{{)o`Ps_sddL!wY-UbnU{+9wsZ+t!LgA!N`;*)YMvB%hB@)zg z>#aZB0FVcNS^2^cbo&hZHy=sOkP=5j!UP(L^ot;pkkV4E)7GHtg`5K~zqn4l9mw4P z7wmX;+9^ayxP{@B4$S$d!giMABqyKBk}mm}MU<4;VrUE86A z5$!}3B`=zy1s%HWTCobgdIEuXcVns-<5{wASRD1-NjQ0y*=8S6XpLfy@-!q{gzua+ zG9r$~Qj@aUc;Vfo2Ja;XX%@>jQ31>JX#q~71!*7YI67n3)GO1c27jIG^WCz2C63Q7 z@lqI|q<|U1J1N@}i))D)jO#pXS6lk?oKfP&f~jQssbBK~o?^ty(5+Uq&i(TeT9QHl zAmgs>j}@7Z-@cn0UI_T$NlOe{rT8$A&bxNU5pVZ`EqtPns5$&1C1EiucgJoXk8;of zt4AKKtGN@JdE(`_IGH;l34)<63N#=KcAZ-{pE04Z%?_u` zvfJz=QlAozGo|7yw2bC8_8Q5vm?>}7uDX4xMc*vSzZ-)W5ycRd2^pnR;gLj0Hp7)m z=hX!5MlhP)7$^20<$Q)L4|@2LrB#@R?iDZ7|Foh5@6`LTh}(OHZZexE6dd6bV?^wN zOMyZ@X&+ym)z+Bv-_IjwAz$}?*4i>b@K96mO*erBDQyj{uaXWGN1(n^BDG0@%ne-m zWhuMSg#>}S!zHu7bWJH6z`!46%8N?Jfwv?7X)w_^>&VHf3aCR9}CaHF!$3F}YrpyP3 zajOU@VKWuwmF_+fBR!nrWarp+_hs5(@$Av_gIX%rI;kr|XnL@;@g<#%EfuuT4>%QHYQ*^;(cX-8gXR^L0P z7iYR9k0%O1S#x{_4i%7EJC**22m9RYlgv7Krs%|i~4S0Q-1OG6hxgrlCbTrN*`B;;) zpai7Xlfz;7rh#gKaOGWKZHZj^YR6!-JbaM&(vjqM|265)8vWo%@8lM}WKPMs)`$F` z*|>#%+dwR{C@I4QD^Mt_i38?OP0FH-B9$fIKB1uVT9F%OR&LK?Ti437?2N8n1M&5N z21McO0JA>yvs@)KIsfk3hq-Yw^7MS?=UXCP7dFY~yMc-=JE3kZiT-^{uG1%7_na-S zFmzf+$o+kZB1Ui}VdHhw=ci*+2g{m%-`@`CF?=PZjr*C$WvrQ-;nSYG!Fj7Spn5oA zp1%6;K9z}{6Z`(UkGs0T)w}u4OYqE$lrDu`uB#<`dWQEH!cts()lUHc%dUs0=5IQcV%{b%Y(2W z0?Lx_v*Ri6iR7O`6f$v8$0`DkZKtD?}(&e zD+?J2ezp@V+wrPHAbikpxrlwlBj{PCrS67i#HsXWpgYQ!!ssMm**z|B(95~N$xsjOk z;bm16{1Tv|&LFcy*$)@mCB-R7Fk~2}FW;^eXrFeKZ1nM6A3x!u!n0>GGsT!rf{6IU zGx{R|H@oZti(NkW3nI?#_P!cq+>(9PVDasd9w_n&guVhfQW-TccbLV+AHg}ifeTc` zH~jQ}=BJ7lf24fnPP{IB46>pzNcr?M*4*h)5#5*iE&99zGhse7rtnCe0hEH<~R|}@g-b&sJsNbf8w+HSkF9w-WWJ|`u0!k5}nt*N_M+Jx5YozM-N`lOfyHM|`Xe2IJE2@1CDA7k{^D;gEs!@<+0ExA(7aBP_shx045;p;w|{3co{ z=~(voA)?5)^Ux03UQ*spkvw)*eM`unI=T>{du-a{{<@-?6 zNFjf-bl-SYt7_Yc2l7chIK98pjDtf+*DIESqc$$Qoo;>DbX?j#MENalcwBtZ;k54Z z3B$JX2B9e)mY4()Bmrk>MnbAPdZy+Fhnhqp4(O#Le=d1hPaecaoIgl+^?Nw9pK|J$ zK3}ANFrz6n5;JC&?$+M;)!911c<|4$BWre(xGcA zO;dY)kStA!$Zt3;7T_me6^F`XSx0O|4#^Ga^n!0UcLI51;eTG=}b;m9cC%IT@&%t3EpcNL9e4=el# z$ClRRQUCz#E!*#=GbWOjY0B+A_0%2$Z1V^Sr}*~xXK^`cZ5;_okU}1Pk@lx~z88O;;2 zd>A(EbuWZkzWPa*Oqns79!5M@HT)cZRWtDc_My%IAoX@>%C=0XO%7PJ(c(SDfU9_5O72tGYmk$_l`Yld6Ri|Kd-%=Tc>mU zvz09Z>lju98)uMq_ro-xLJ+fJFTVzF8+#z-fx0}l7}yu~82)CW75JJ?Oz--27RRc! z3YRrGWp)_ZRZM&p9hgJ)TOk(Nc>xXXD3C~?7ic-`d}GNhz8cuNKla3o*USp9{chjx ze8v49U4ykUKC<0{u!i^IKNk`4(sOVLFngeBHv;3Ky&<6ux}9a@D+;xF{3DhmbGh(K z98*8X;?(z^xHWU-`fIE-fgmXbdC;F0?A{*237-fg&c23wmrSL9O{e#*T6J?N=pm}m zHU;a%kfy%YAvi8^XOGr(J{d>0(#*_yrQ(;%otTJT`?p=LJ}|&#Wd53-)8U z|8ZI|3FA%@Eq%hYHRRYU_Y43q_$PT8JfeVy8%^MdQ1*3b$xq^BpkLRR6A7n6K^{r^ zZ)*y);11a(;M&BG8?FRVfmY|A9f7UuJLlT#V1SxR{BJK2d=tiG7L6$rTq2MjXMQ1= z3MB@h8GyEksixN_rG-%_aGx0R)VNK?r4JoCYWt~%BtKW?FbuoANC)ULL><$o;l0_SMGIqsvY(e$IW74>UIF%O?f0N%jk{Q;D~VO^ji(5*)t9+B{ZhBFtDC5^m#7_Qbd)Bt;w@uKZqM7PaCykA@2aM zJ1C^xmc$E`VnB$~8PE>4>4<5K;UPMPvYX-a*3zTcx(-@UPN&$k^q}ctBIS0&4Vhl~ zRi|8(v5%B8Ri}%cw+rJajo8`wey*aO89b^VcAqkqi9E}}&MeOm`r9k!3dqnl{Zfg> zjg3nfn7=9|o+m-gz@5x57nGw#_nVH29cp@bAwC;W(%s*JJFBLz;WLSEG*u*h)77H{ zIcaS!Mc%yW$}J;)-Dn=;FvX?-Llr%p4q}D*Q;OVG22#05O77VL59Z9Nf@c*&NyOKg zI5#3hkgT?#EN#r<>2H=|4l@-nEJMFOxaW`F^Fxh+jW? ziIrdCL_Y^rRF_lrA6YRq?WDP9D(S|ArlAH2rLmgDw=Jg0pOR>_4GK40Hbos~9GI5n z>I-NrV8;1lC&Z7nABWV_`mTTzk8mhDloPlzl(}G|4i3Mi4S>RrK9X$6Pw$gVQ$PKr z>x6z3qNaQo%qSFSK2V;9gPbLKDmV+KKE4jS>?%0FH{^)XS^6%)=y%AoiX<9vTrSGb zlEnTf=MFh#=_m_l>M@z|hAhxOo7qnS4gIOGb=%K{f=v4<-GAKH)je=$8sw(TURfDU zWm)C?&Oy^uDi6(CBeUr?*1NT5A%UTDuRY}=`=s0T_8oUkR(^I zmLnzA5ir#hCnz8{o;A)PEI`x~wV9s9=LuZk#P{Myv%u!^|HItS+|*g8R@izaiv`T_*XOq!#-@l;VcuF*G6-u%?3|d zWl-frHS~h$f(AkCBeE|uz4xK#Hztt)$cu4QPI^4yl@EOM{&Y9PCgY8H&=aGaTiHY)Zy9gU}1q|LrQ!y#)b=ZJSX~Ju0YiK2cdB zcn7r&;ip%BB;KNysM(nRUv1TBW9%d%s-r`kO{@GKDZecUiB)^guV>Zjj|S_&qdFp# zLACi&gCZcZM)V?h?Hgk=X$r)MyJGd^?3F9@?{+%tO2annvZ{yT8vsIp@<=n@*46d& z841suJcX|TDAf2`3Q?8JMh#e=1|R?}uwm>Z#~iK|+1$lJXb|T{{ja8~47TH8mzrrF z`G0qvv_n4NHB}G4r7`z2FHWHvam58*96tk4UVC(@{?x*1r){Onn&;{_7I5TB)$pWXz2kgd6L3kLGDD;eR?B(cfXueh{jzuz8y} zoy_;m&>9gU^u2d`h+wVc86c=VD)l68W}dA4&!+*Ay?;gmAdX=!SiBN)S3V`@%>^j! zZ-88ClT2~TB4SKw|<7P0@Gx)`2ApLCY7?0yOxKlX`%xtA0+Sr5J0MN zT3VK8W?kAx4HsP|)H>WA67`w`vu}|F)o6X5OGQdt zX@{q*R!a;EXjTVY5j-`BBZR2^E2KuJc?|$5k_Gd{)6_HNaS_^F-)$m@mVqh|mcaBW zGZR?2&dqfMmI`|4cGB`SjV}vR4CES;4e*}%6}zK*3Pn2}Ig?HZ%oWpd7vUuVHX-1% zpUp-VKZo*K4~nNFWK)cC->9p0{H<@MukzOV>b64*9DQc-yxzaZB^d9i|0}U3zLM#Y zCuo+m2_xom!Tn>=AZ$4Lm-kF8E$iRiNNIwgNuz@pH9lr`jwLf(t_oh8@xb|iv>!OT z8uH!YmC09-8tF$zSaC^8cu0g@5*in@@>BLX^sbf4?s)PRS^LhQxnN|ZCc~BAnzm%# z?id;%qqK(<-<=G-7}V^;>IJ>HL>_>+M&?FD!TN1}5k2mGfJ_^Utln1(FnG4;6%3*z z1M@e(_bY{b6?rgpMa5Wu>mjW|d#%Cw>BZHEfMkFLa6O#SUD5CB@5|Mn=m~!QG0A3x zV4|8(3;~&fSdK_289d6Db%^?X#D-xQ2<$`oM70XWMTPM=?TzcvUjZ12lhXOjt<1Z_ zR%5Q;05cyAFC8(pro0nM%vz~<_=+TVcp`mF z*L>0ZhJ--i^6LJL_YIf_@G?gkg;WrCHW6S({G0n6(%@h+NG##C=Cb%1D~`|lQmAMM zke(MN^o9QH1&+v&)td;zya#;kJ6nRJEy9GRsl^ovV6w({G2^atRCQ^*OXceh>-)Yr z5_~Q&ujLrUFO2{g0k+rHdqoyGmn0*pd_dpLuei;k*WOjGbh<(qvr)ITU(T65CDYX7 z4x@NjUSD_T2TV1^O#Hn{tX= zV_MI0LqEGyH#0xKQz1@<|J*xpjk#>KBF{RL7?CWFc%z0q>U-3m0L}4$z|@ms|Dlt3 zMOs-PSLyc&WVLohHA@zJQiu`-SworOI1| zRvCAb>06`2ZCE>hoMC!Wli+KJYDj#$<3FowMphUVX%rsy(^#741Mh)Q-!%n=U;dsB zn0>l@sAy*I)`$zr0zk)F`%qn+gtBAx;54kQ8PywDH{t+bli5t{pToo6@+hL#v0wYb z&V(&pd+2~NUHE!)^WVEWDzt;>BJs;@C{C3l;sg1$8I%sj69ATUDSr9dFjYDq-hNmV=4k53;&c=# z8|GLcn4YYWW7>Tbkk|oVTbs$lU$Z{3ly8Fv3o?I|?mw@%W(S{c@2=yEPuOAGP9bYJ zE2djmiOfKd+uB;3A;{}R9EQsM-E0_}nzF2JZS|67)&BA<5(Q$?R?PFaSl`+m6<7Hw zD+I|wKgMVeN;w^&BdijQdKnW;QKVSS$6#aDmSQlZv0nHfa1xq3;*F$ndy zqX;RFkhjI?$-@{R%YAh~Nq)B0F5RBzE!Ng|TVd;$K__IPB?s+?{C{>G);fdYSYj5* zi%*H2VFzYngrn2Yr;_0Y|qrnj=_MFQjM&@l9{i-~z~XgJb$QJq>& z`ZjD^HZotpy1j-bDj~dC_&lr?8R#4IOroc+GiZ5Q36DF~T8i}@dLLUk^WBbJM-Xdg zP_OsrU#fbPx~Caj{pY=Xop8)XS8%nINVpNmyP8pnY^`MQ@MU+OHgiADwn27Z6@Vj$ zkXOvH`Qmp96SK14inOSRxUu+R{+(f6M`6p@D{A@5stB`Yx=+LSVD9MEFCK?w>p#ID zqOuH29842pC6kc4U-O+-_u>*+15v}HWD_`+K%Q$yz0-O?$flBxPMCU;#!>>*7n>%x z6PVU3Ob1BBC1w1YnS9>7k_?cktFI4D&OF`yiT)02wrzdd$M-%j17CZ7OF0FtDSU^v z3`C?85sUaXExQT0Y^kmOPF7g<1xdUlyq1r+xw-Y4Ej<^GkUns~Gh9Xm-~%T|BAo4V zUz#%FfOY;B2UJfPz(!!rie(BfmDIzg38<(95G9YrXuw@b%kAa%{vp@rPJH!`CyC{r zwH9MfxRMU!nae^0(FqS-?tn`z5G4Z{SsG`^AY~hpI6bB%{>bK6kqxLh0dEUVcz<=B z2|jodFu*K>l;=4+o~-zv5%psb1Xn-uSXv+`h8B+%{EjHB~Aap!5`=GJGdW6`DFi8V2-g!AaEh zkl8A;NGxzL1we}I;MQU`z(>Ub!kZos2_9kGUHL4BGRo0FQiy3Zpr&8s=!sv^(+8G0 z^~JLzKmC7J4NmS3UwbyYkL){AQjt4t)^#1P+WB)%Z@!|e&@wZl`dpo^`E|+Ven}Jp zCYzR0N}prwu<)YN6Bu0Z_I$&!xm5+-ty052prQf}A|R!uCGY)7LSa2$Y=k#}}Z z&Ju7?tZz4%kI+zC&Uv3N1$+B^O*L=kasiBxqmD^r){WZ{jxKim@N?jx~0dPiaaA{bWgN`bit1RE489r9-I`Q2VHwzcsz znqesmS@+yoflNu9pM9ZJTViV+){|r3CjlfB{{lKVRRI!OB}F=pLAt=c%U2P<7A$HY zJYi?>SqJ-wx|w@62)_;a;i@4#%Lj)awqGWM))DTEZ|a8hn+dsU6X(qSDd_nInuJ^@6Rpfij1TOhlh^ z731AQ%#!kj1k)m{Z!i!H%E($pY7KHMDnQI^hWIQv7^RhS^}MG95=1J0ILIg6v|a1RN#M zHZ!9gLh_W2A3k9NGW@|4^;o8*^r3N>oNfc(JADWoh&GSP9Q(4_@;|XqV4>%&_BEozoBEd$(bMgEA3~|r$i59Puto8^%+ksHSF?xd@rU(!^4xDlRLQI!#l?VzrgL=s6(I8Xn#lyXM@ctZQYHn zx%Fd9(msJ^Mjc3zPse|;eR3p}MN$NamNh9P4~EXZ=C^}6Q!*LFyGTTQK(9Q#N^r}w zPXJ;}Jfhx+cn@GQO{yNs7WNJHx?T6%6voA!35*Z606>N^Yn{G#85}b=YyPp@+h(~M?>Q2Os=5I9 zJtX4)F2)m@UL88NLK`s7_zG_%=$%FQ6ruwVE7gW5KFU0EE1F>gzdP`;4n! zWYHQ++1mUX@0&Ej;CEQ`n&YZRfrHBm{1|9;gJ*2{na3xSu*Z}NNJHfz1Hv1Rbd`sp zW4{3wd4LTbsW4R8(GlD=&DVAfKsN~l1g4*|05a{^>Y+5SX)vNHF<>U`GVHc4OM==r zkEKvlkK&UuXuOE&XSJkUMdz0wdJ!c2@ z6R80)vsVnY&RlT#KCo0cv_^L;#%~=k0L<^UiU8PK-}&X)cVN{_5ui&%6PJ((QR~|| z{?qn~-uE9@8=En<;r!{`nZl+Y8G%E;2{^r;S0_Ln4p5z|0Ylx1l;;ogZ=CGgXqKHi zzh_|j%bx-v31=jzrj#X%67Cs*H{O>Lg#B#+;q*0f_F@UuJ^K2iLWqo{=Ix9Y#t@aZ za`Y7$zz%{qYy5-X{b*@GdC!v1x^Zv2^GOs3#!fm$w>iK9)mT^kjaDsUpCBQRd26$~rPF@i z(zjv82M43A)F1j4v(Q6RO8T%rw*20-N`e*!Xp-vCdIEo06Y;PrDOMnOt!$xKZIren zJM(a%#QgcbAYujaCJy|?1M#rz4MuwG4LYP7w_6YGgn0xAFz#&3Thvn7^fygkxra?5 zCBNc^$Hw{r1b799Sn_O%Dz%@fkvIup)*qol0Ql{kX=46)V%H4HZ!XjgmmzoSH{kxS z8qO3KuZ6%_%RfvE;d)D~Fgw@b#Wk&_jy#lHH2OoKhk3|DMfXDT6ZmWsEtomgd}Swk zs@qrVGzrM0;ra3o@8HP#rqTQvf;bHH^z?qUI9m>&WmLA{kXAlLaJ!nHZ4NxT)@4@# zR-UQqA%wsHGlqj?0h5Bu@!UpZPTSCzmP9K271(^RcfSO57M!BghFo1K-QGM}KYDu# zUaxf^H+@m|7~s64V4!|y@NDTYxK%GsAnt>eyoUiuS}nL33tz7|OVn&;_MBb{#&l@U z8CM>`AG)-l#^UbWu&8S!5VN%%56(rE*WRxXLF(3Gxt_BTHAUE-L?944Q$#MQc5r%N z@A(EgbH1ZjuB~#dN^#ZrYjU@PUI1=d4nm`o&_i`vtTWG>Z#Dagy@4o>3fS21nx;v| z0bIQ5U?>+!kb8CC9VWrT;^Y8g3(`jPFzR6>VvzkWtcn#L*>GpN%}2(}hHt?==UZAa zeV;`qFo*RVFZ*Fp4Fuky*ck-r4ii?ag5Rv!>qp|mZ}fW0^iEn*TU3*W|16H(lukn- zX?HW8D)L)tfj7y#65&Upqv6~H&5>mVOfm1AaJ}P-eT*rjpWA{cq75?45D!&^nY?lD zBtO#ckKMpSUYI0&8!y`lQ^)D z48vh-nr4**b)o*9n^o__!sL1^q1!3NajkRVT7RhR)7{0Rk+YmEB{hyg zM5U@ZB9@3}#7HaW8OS1-K&a-mG?u&_Yrl-VJ2gACEW{)Bf$9X$uXOOp>DOeuwhgX6 z@Vl2``};lgg*u7w>U6krh8CoVuNhA+J`x`QsoHo|y+w(PM_o%5{?DVO2chst2mwG8YCgc#A(Z^$1dlryE$94cKor4{!u z9NDLfEld*}3B0fC?$P_Hn%=}a(LRz$S7%=6t7EI=N=h#*yf$5xE6y7V_t^ zFVN6Te)R!|U@x{lhg_faY#x5k6BY=6RttCe7^o67_AScjctNFk?T)~o%rKPo<~U{N zs^DQ`F8TZdL&UH3c~BM)Sk{_fruE$e$^}ERcDTtR`TI1^eYNT{;DblPg|$!7`+|x(0!e1VuIP{V=FBfH!RVc=cHhBu^Y1QiU<97%+xEdY4;& z!eP|MnW+qP>@0%N1g-Kp*v!iowz!P8^eP&c11s_B(S`!wB^%%%pM2d~aC9T{Tj3$@ zIwlNx+k4<@0o93_Dy<{Q&#{lH;7PKJb=7U24C0E&z@t-@B)oChT=;@oy9DP>nZv-c zkE(S-G?vvy9!k1`fsu<)*_luVK9_ACC8n;XQKl5f3`NmRm1&vZ@_%_C2e?D%lJ*f& zUivNEe^$$}rJO>-hj0Ay$IWbB{pAqoy0kR?8+X9J<( z_RbDqieNH2C#xoZ%|~&<0&%L7dR;tL@?bf`B;p)c-gSsEgD|b`MY*D-2K|8DuDfyB zavjsqbD@OSRHG4SZpm$bDHGsV8Lt302403&wkK;#}E$jaC_Ksg)H}VtZY4o5PjpdXSdA>FE@SZvKv;}I!gflKr z!~fKEI-k5zSFYLZX5VMEyP4u9nndjokA`mCSO1IM)3#%(w8e$Th*erR+Cng#Hw?+7 z-pMXJU$o&N&d+iDx^qyl)}v`iDO&peXZr@e6NXrW?QZ-=z|#YQad&8!W370#3Qar7 z?&d>se$9%46(YwU0(bG_UPG%d&>ijQ?R}x$6q&*e{+?60ilK0d@G?Mv&=kh?#pc(JCk8eJQpcS73n}N@hFEk_2>}RM3+4=8^Rw(F0E3_vto|r%9qI8 zG-qRSx18*#9kO0*7?Y99o}Z=_enA`$(r7bRa3Sz^y_d5R;I%!2I{|fjlbMMCkn>^l zv>RDZvr`PKYPVKPqjtLp-PL>EBT#t2^8C7Wf?BLrD{;j&+Mq+k4hTp}gaOW*G;XT| z6XhB}P3j_}(8AmtN#-9}3W;4f@pheSG{Bh@?2k1IIKS=M8Nyfc8u`;myu2lejKP18 zrN+qAR7?{KV;zpfl%I?pnmaHP=SRGQbQU=jMO)E}dzr5S&F;76j@Fn-1##6sl6_T= zGydSg*6JK5dSryY~Ic?|e1kjmuLiHlb$t;eq|i8>>ZcbKF#&UKU=mH zm_iEJKr|lRtn38Qk4?rZ%&(R=E#5MDUmnENlWsbGyCffD~Yv*_qNU`K2ofYypy z&C1126GlcxaYR$-}Ds>y)Sd>$ROPH9PUUQX z!tCo^eKYp~Znb0%KV_NlFesi$0Z1y0BiZetE1P;iNi>ZOl7ZFuR~4vjF@vbgp8(pU z-l>MZYbsnDcG+~Gb3OF+N&l@56pT!VfSr~-P>Q8V)`6A``S3Z6#sC&B>EkmyAmm0& zDR??=JBcKsE}~UPL6p(LP-w)rVU|r-hiI|LzcAy8I0CxhvS{_@&^)zvN4^!bV`NXN z56eI2I1N|IPqXcsiJ9we^9}GKYG~M3qRzx*vqWPZU&ME80@R;I1bL1y-= zpg$4r1XQqMuyAmUZa=F(HrQe^kETX6;?aypvhw8t#3`i#b5Paao{$Ez>V+{);vChBts#k4nQ2h2fhKmYbBM&o zi>S`NMESkZR%%+`aebWuy3~NlJW)M3vL$MI-dgvx314COm0C4@@l%c*!C(nT6XqSE zXS;l4eTIuHW|6$LHIpdx8sMqQvz*L+6pyp-yrTnz{ur%efIA2FsYUDBPvAUTIJqD4 z;|j0q0Pu<=5hli%y}%m4eVR5HVqn_9^qU1}JDYNhb%4x_z%mA7=xf7;Ba6Wu7h+iA zA6!&D9xUQ_;z^sycu4lCA!(l1dLgTYr)kbQ9i|l8lYSr@XTn@O19f*fp1X7kpepin zabsh{!Od;3RJ|Ceyud?=c#r`SPUmF($Dg1*=~7QuL&LJyA{`XCRVU2nl#)6g$edj> z{uS^9=(}4otoW1CRUC$G3@KBqFdB#v-Z-9aBkRdlea81V!GLb>3ph-oH`_3T0mQRn zX}kjic-m&XAi&5V@Y(C~(^x+nVAEa%x&QXPEt>mrBg_R7i;Nzf#UaeM=CCvE_bu%} zH=f^V(D8RApMZa$sv9|=!ou`J8nUzNxxZkpU2=nQd!IcRoo3yL{u8xZe@&g=!Ikv6 zLGUZHYELVdG~>-W=05`kHBTC!%)grtcuyRw*F?R{sr00MR1@52w>Qd}1b@_H)I<45 z0)?a!hx7B?OnGkzG3u9syn*YTz+dm~0U9g0s+x|5cNdN5gI_ggYJ?S?OJTruZT$Y` zA{IKVJzj0Dx29{jWA8gr=9w;!%fF9(SUFn>5Ot3pw6F5p9QsYgDLuRHx{iM6SG$q? zkC%_kHD@$sUh8Axgij#q z>o^EXxpSA%=2D%Hyg@p*G+{QsCj_^1trmTLNBEr3zz1?V;o6*D5GjD%BfLhv;QFk6 z{C<%Ky9xru7sqjCD>fiD+l|P0b=w3$+`{+%)0@QOl}vt~P4tx0(dq{r~dou0g{r zUn%I6Eo5n8pO0j;qmLfA+SJ4vjGN$tBSQ|2FEc!rP^u008+WLlKpGdP2woL6l^IG= z)qd>HRJ)S6Hp0m7xN~k{-Pan6eVl~U5&1bJ`6>&GP__)G39H*$_0!!=$)puQ#z zEPUWi;&s2u3Rph6)t!s!?5k?=CDXS3{8rYJW<{SSjs{qj*Jxpph++?JkAZ~|7qG8i z-YF61Q`|^_#u_GJ-0j0MkQv{Y3vZd*whltE=6Q9Gh=;RIEJ>i1zqyk9NDrE>`@Z`7 z4}FSX`REw3v2+Ip7^U6Gfg+nL3}`EU0$ebn#s*gbSe2;SRHiR;3|(|I*v^0^<$|%tt=bHXGJb zR9{iB=8_gWMQx2}Yd{T>8X)ZzI?jaQt?s#EnqQCIl39SR8Q+fnNPnDTqB1q({x<}2 z9Q?bAjfyp<@WPYHoXXgt^*1Erc)51-7pmeKABN~i*dN@%5|-Rg#udEPgFFKS%fBoN zLy-TJKb>9J#>4Krcvmd<&f4$LK+w^vb+m#4ANh<|dn%j1>0QKju>o6&iIGKG)c~t{ z8he~2=mg}P!6zM1_XhCy!E|vk;K+WMdAP^nz8i11@T61)5pl4?iJgbWUIQ|YG|#>1 zk|uq;oVW>qEaaJ{Hj_P#+!?^{n&I{0lD-~!e}Y= zi@KjsareP!X(f9@o7uba6TnOLbrnMqqD{Gk`LZ4YV;fb)qI8BW(cvRIbzHZmtlDAz zFC~6jpJ_v6NC(zrc)QuefJQ_)AX@|^5IszBGx2F80hgugZf8b8O8>2+# zS_LV&QoWsPyyqz%)*-GCXv8N-5>aT$Qw!owumOr-F3k7v_E7QZz!2aPIQ_fdU^th! zn5E;`9Y;kL##!Bao(TJV1W0CV0>`T2=UaU#A`%Pjh7q%-DwIKc&`UJ(2Fo%gZPmVVyMvuzqz}7Q&vDyVhPnyrSS=I zfr^F2b{iH94WA)%**|gYA4=_mr}=>1@@~KQ|B)vMyI4TAK6Zz`p={y5g6BO||NUUx z-{b4B+oty9aQ@F|W2h&a#&5uFK7YY?Uk0jLVGMrbT%{iL zklc4)39=-BX&OTsmfHIZc59>syn>NXsbp5|;j1z23i%_5o9{k85ZKqH^*c8Q?0oU% z@tCcSw?X*tR8e08eG*pteV;u;1{he_@ctku z;Q<)gW`sU<-X9$150Z*Yya51L%$l<;{k(KFQRtaC1Y29geA46)qpDRn;cs-jTFlh5 zul!N9o^i9CU`*TKbDGmYt~GLS2|z4|_L)!mpxCJ8f@eXHeMs5ce~9j(Qm4V68@`Gt zfPC_EA7kO;?XU0pX>FY=zkRx_$QnJpyYB{Br1GwBbW^+EOD-shJdr^rCc9-f5V(wX zK0sHSu!gE8HnL&iO>T=KZXI8IScKhS*_fcF<%Np&B%-|uWe6KX2Ry8&4BGtdLVW9~ zM>A)|PmY-v{J~0LMMf#(Sp3?u-_ZwYDfjFHk7nz1LW$8y%;*%qfF!w%w$_?UE~ zGCOV~iO1@xwv_xwW)TT6t4Z1q)AV6;$3J9}alAnjF4f{3b+Ytcu5_KB=!Q9s>f8)GLU($!+N4I98L#MgPl$py!q6F&^pFORM%7QB1_$^F)$OXp zeYH$TEGOXYbi)p)s0kp(Ke>h$PnUt>W?Azoj2il{v(w6rl5Q$?RiJd}@ZO(zI%Xm>q~ z$4OnI=m5RoK9n1lwcOA(ixn)pvHzrU1AP)Q9U6{EhWue*Mqarx~pO+WjK}kVcI=u|l z*y~8VY1?%w=5QvoFd{h~d-R{Y5J7rzZXSbeh`NF@y8 zp1R8-Y>wZHJzaK8{eg*{@5a#pn&p{|c!p7};A+tn;I5bYr(~)g^)DjD#K73SY_GSy zf7nOD?-h|Wb$;h7s3oj?FScsHBdu+wTZk}JT+TZ5EN=vC>7u8eo#4- zQ~+1k$St%|fH{?9p){}$bYgsa8Oab?Vkts>mnP6pd$_HF9Gt(lgzpec0cJE= zIewoBwr-cEliKH%&n#=ga9qOf>w&9n`^6MAmjpgd_DGq&^QM2MTGIY9)+z%vlN}L4YQkAF*<^>&^e!Y+hmPd0@0`)X+Z#qHghYPkHYDDx z!{4=crI8^-JbS^Xp7(*_`?d-G=|FvNsi?z4a`6-tS9&FU6xJUehwA9)ShFEgUWJ>wM_KGD^?8YQGMx1EpNu$iJ^>SA)k z45fXQ2~4?_?~K_beyvTwyRozPFLJv<-)(C(KKY&frV`}A?p&pJiA1dh`EPm4Mkf?8}h@JP9*6zOf5%H)<8w%iQPegpUrax$+%tzXa`sT4ei`l95 zE2{`SuSLdo3yx4?`(!o9MYe)ReNQO(A32G=&F(QC;(@gY=pVk+({)B7i>dOdlQ0)g z=HP=eN-wH*>TuoDuKb)mGWZl}v!mC+iSZo9YxFnFe{+}S&si9goi z-`-aYA-%4lZUXXN35h@PqYZ1wi!n$!?U4vx3*Fbxsi*OMMhh6aq4|I^sy+Q(kB;!R zX8ZY_IDe%I>12y>A6!24s6G%( z(s~mMj?JB?-r8_2Z_rBcM3f*uew&f4Y*O<>a3v;m-OB~j=MUX_wXncm>j{sKkS84a z?cw13iyv0C;(KWQ$om3MlxZdwY1u|pL0a?fpeq_HM7#?uubkXNeV1UVn#eM0x4#?4K6$JuZ{T=uT2JRnOx4j(G}fHud`?E z)%K6ABmw7F5`>HQFf*^P^SncxU?l&ZpS##E0P(;E$!@$E|sc3&+d4m$QHPss(BX+*^ zN7b*nhA2}U0P-Ab%0l}6 zsoBjBc|Ppn69T#wDK(cd+8`Lbbn2YZS``OsfQg9z-#{u&H1wmIVQ|h?^m!j2=8t3T zO?&6!c%9u*J54lvh_+ra=QosQZudjWl@@-9<6fUFYb z5iB|ad4Dbi>Bf>UH5+BCk-O;V%NqbQf7v$2thUTsI_nzNUqYJTv*~b@s^AkjgB-%-C`bwB z6pn6)E~&2AnwkF1q9KT&n=9PF4JV)}0Qg?KKg`mV@gax3NjERSf@vHJmpzGnHx%-> z27S9A$JlXaB7^o~`s0@&&RYwO+}k2i{LTlf(Bd1bVi(OWna*$s}e}EGN zWBTsDIdr_7jAx!lR;$!%1OudiS`>!3Mk>1%j6*|YGgOCN)X0*)z_yg^MO_f?m z&J$i-yfrD{9r`k9CmA&cZgp{D5gqz6^2y(bk-UJ)n=pbT8$IXLwE^7@f2MW3+ zdq{YA&eg#tVm}w&1db)m>#lC8@7HFO7T9pgT@r|F#=xPI9#W4*!t2%e$1aT*e*Gs% zpMc9zK?!>AQ?DtYnqElbOa0svp*l%#xmkZtlH)7k*u_dO4dcc@`<=lEsq+#1nGwZD zbaKk0IgE7m^S5q){e*V>6Rs)j4kv1SULl};ayR=#hu0+>D+9LkyhE^MGP(2ii@MkH z-3PoWopWjS1z{eT&O@z-b0Zc|M_py}4oOdVn0EPdmGAvTNsHuRaS*eBHZ*wo^j zKwz2uYy6p?*NYq&;-bE8<>!_F2%Rm3jrAp7egc&Bwk8%0a`MDJN3TU`wn$v_!xuB> z#3V6x_CDp_^e>lN&EA=ePt9+H`KqwKhj{_e`CZ$;wM3kvE@*ePc0&9>#G5weqe9D~ zjpn7J{U)~YLG_NDAretzHkDlZ(C1ZrUiW8GQRyT~!D$@9kLKlm*%rtGiyk%felH_N ziuyGqqgitRa>m`{!A_Z^1v?g%=M(d&dmsIZbKRaGV%z!bzPJ;Nf3Nq=qSHHWq_7{j z+R^)QhXU~aExS@aJBe%eD~qI-?4nU}^t#nfXN(<@)j7w}yPaqd{chD9ky+YPk_XGn z`r5v&nTgW-Jwkn*Jdn9_b?N9w?}h3+bc1voykrF92lT3=)R5C(-Zq$&fbiA%zc2j! z{t@QJOHF47$Pw{mF0RLLx#Tp`e`NGO*`~VRTV6z^f%H4}=z(k^_XaP28q?=x!uK(F zOSEG*{O0)_arK)oNyNUh+wE`4am%-W=nIm!^3vs_umMpAOaRt|NAXF{>At0Ut;d09 ze+mcqGqg+ip2pzOfePQ=DQr0=`Sv^rgTvZ}#wlrtIpE|l^)})cZ^!Y_MV~%aE*oEZ zschi#t+pdMz47CuJ&x|BuN!XTfEM-Hp~cwaA>qov{7Jvz5kZfqAqOXSb}Wm7;9%zi z1DVGr3~EjT?2jS;Q1?~xfaG1fvfwyDu}ObGYTEy74fODYf4I_yGAjLoa}w()_Pr)0 z!N9jH%FzK=7jXvti9QS8`d)_M53BSiMq-XnwcYs_W)Qhi+@tw)?tTkcsk^x@A?%_cDEDZR5L9T$|fKYZA`9nXezFJDmudjEv)1DkfIq#!jVfYeh z!P8=;nj>{D&7$|;MI!}$2t;slD z6d%dr!AcTsze0^g^baA&RHnwgT2RmJxPOpG)M$x*a-%wN;>#r8^tbnB#Zp@%$u@|J z3@S>ET1D_JA%`uqn-$IV@F1&T#J-y&2|!q0m8mNGTVM}yYB#ekt@fVd1ZeccJLOseOOqB_yVFMNTRPMjW$zv%{;@YUeIaDY0X zHi#M6gHtU(=hc)bKTdcN`jgcgdLL0r)w!E&-{w~`Yw7B^OtG41kOgt20!$~)yo1%M zvZ^*Db02$qsmp6vIrX+4%)-$=^(&W=P4~QujWjcVFxpy;NIPyI4XY;a3*frou$`Yg zl~u6gLQTQH;Oa8U->SB85NpBxin`Ylz)#vtrr-u0a*2&Tl~>^Ya;qpzBmLfp*?{~O zg1|2Qc7ov7^a@oyW)lpMo2z7g4o~wn?$sXbJNavF0G*as4?#9&Vv&a;ubkceY5ez4 z?Yh}#i??{H{~jGhnZTy$(+8KSKN41C5O@X*eRqZm(U z=>AqAO6~RVc;v>*dERmry6MO9xNpEXJv(JgYdYo^caClvsmIO#Z{eaOQSXyqx@e0B z`clZ>!AAGW+HwW@VvlnH;jM5L&8dFhaK@#{i8K5%rUj<{$m@#>WkgN923nqxYlSG^ zkg~|KKzZ|rqDmum@<~Sl++y}WQfdv&g3Q)ji1KwbK^arR$9~4;nF(6pWqdJ`%*$MCg}?_olEsf) zSCm_cYf6oEI+(XDd6UPv`flL zIyFlnH)P%)O3I8j^S|7DJEYXmOtQddURL%!qSer>*}#{2SX^9+y29(O%VTT;{N&-RLPaxT>W8vWKE$#wEuG_=N*WH zOVoN*NSb(xdbmf5oZJz@pi)TeA~~CeCdViB`XTZ;{OaK>v61WkttFh~zD9V4&rFifK5z#s_JW&Z!s2aqA((`BI5Hp+6EY&0^J0SJ?rZq>Adm^)3k}wT_(*dttzmD zh7tMQ(zS$Fsp?!qhS9*J)#iy)Izc9s&3k#4nJhs*W5n!rLq z#N?&CH9Oq|arn%=17y7=5~BIMHUWMy{8piE_*GI@M+;Xf$wmlS&~3cQ=*Qzy3^EN4mMOC@oBC zG|Z!D;vIsSmx#+GmlS?4wd|H5c`Mzz9lOVNXa&1|=(GAu$_t&F%G8|8)=p;j;w%Qy z7rHjNM+RtyV;Kv5Ip+~`$+l>ro{{v;ZG&9NiCJ~IGnAY-*ZkSzAv;XwVCehwTA#faS%|IH2hfLc@ZVJ zTE>XUB=EHqk@mXGRCBl{yW+kEZh#7<&BtZp;lBdbw**bVTIUI zqbPVrKlfQ4sm`iItdx;V;Rs80;cD#WuS%-*Qvff1-C<$s91@`0n zo6#HBCUOnbGw!MlATi@mnX;mf#i;*L3F%GOt$$OHZH%+9NEK7mDqjFp82EsD*94*)v)*Re*;pU9-a08x3bI|&}LB} z1_BmJ5(Eo)RcuX%EQ0)SpRJPxWlUIOIiL;)FJ@wvE%`UB?`hEPImI{dpIwz+OW>y; z7D$Fz`%qFrd^R?=UTsPD5C40_%pcPm*s1C1K%me2B8NJa-Nv54Y#g#s6X36Z+;L+7 zsK=pb_Wu6wlO-`FweR+dbAX}^r9>zqUhmo(Ie_J?X=n(EjlF(O3Eunf6agKyRcb0K zUky6E&Zy#2Q|UD-Q&(2>0M)nH7s#uWoeFI$U?_Vjfbj)#zynI&JE96&6*`m}6^Vm` z((Mn&ZI3o*IWLc4 z{`7EjG1>JBgM>nH%Ou?;{xdaLVmh3x3~0+Si!*%G&1wv}*zwDQo6&ym-6`HDKW;>$ zY)^(ZnrY#A#H;_hV2qJ=fmR98#0yP%?N)}#4}cc*9F-{A;9&(s5>dW{3^_MUcWcFPEb` zD=MI=FmCi(($b+S4L%DOet-_)-Mqv3_D}KTIAj`W$*{3(Vck112K?(>x2Jp8Ts}(L zgh-rQyz1)Jb}9`-@ys%t(bHp_M29*R+V``Rq9&K^Tns8HpX1u>Iqt78S6_smgCmNU z(OYL_UV{BQgb@f7E;A&B{2o1?bx`nGFqu-&mYI)cltp)PE?)67_g!N&$@8wR`rIT*1(zLobMX0S+LO4b&)@XE(%8t*cLL|!lglA& zwpB<+b z71{#W2&`NJ02rDtuWQmJx%|St zfm!`G(D7pHy}?e6PN87d>l*aJ=dmAC4Bm1|R+$}_P%OeRXX$TXgCU9mujIj$asZ!cbI*DgzN0zk_Be4Dx->V$+ zbkI!)p&L2NT$4gUk&(#2DDhrLnFb3cRP$k|;}fLRcPe*s zWTk(@$7~fyKShSt%zIN^^W%z{N@O&M&N7&wk5G}d@-;~-X@v$l>MQi$8QLP z2d800Zr5R+(_Wr$x{@y(4ZQYfb2aZ3GkDPe-Up499!Ur&5Xx}v-0YbDdb>&7%O81qpA7z2Wpw~z`h9m+|lmy%jtnmc5 z6w6>#hu7w$`b6$H_g+c{ztA4-<3^{<=@KUWZD~r^-;%zm^V3N*i9RH#IhV%$3gFNyK4y^5te$ye@Wj0 zJ$)y=M-xS@ROQ85C@>%3NU}IQItnqEF6xkS_(VcN^3RT&D-f7CP~%%FG0YTkl=Ev0 z>8`eyph^MTYUF_y)S(}~-c0jsbw{r3WWIm#+C@DmuccBOyuJPZ3{;;koMaCL8a>^- zHMJq^0JMics~NLJ4R@aQqI{0k7gl_%FdoHG02YRV1)7v#hC7Q7%vmrQcd_YEaqRk0 zj{TQ$F6*i!%8?hAk0gRITz>JxOeaQkY6@@B(S2bjeSP2Fv%dMBS6{E8z%gdbbGW^| z%^Ukkcv9qn1pvX`?jRsu{O94}_kX>b2adKkBSS6j50ZZ6qzKt7df9X6ab4vERw|(& z`xdV^xTjFmB<3GM9&&*=fO%l^YTl6GbHOOEw^pP>br$Gq0UMWlCuISgbTJ*wJ#(u^ z>v>B~WhA`7Upb-M!fETbtRMG&^n61!rAV$PveSug>dioM}1qtZd@;5PsnY{g3J|f|0i&aL%GB%oyhV;jX zV`n$Jl2AcXTP}HMJ#|;{Lp+3HEC=YEh6lR(d$p$nkH`U{8ha`>wvQ#4DQ_ZF=_wfN zj%77t+SOxEO_DUT88r}lA4|*2CDhasPLu1yBO~)#B=Lb+3E*zvj>lD1(J>wFRBIx? z_V)bbhZTl>lQHhY5J-W@C~jg#QRqsWM=u|FRoE%_GH{?M! z94wX$v+lwr#PPnq7vBL_P(ZDMZ#H_i*B(Jkhx`i9br^}Bl9NU;j>yKUgPQU6Lk@Xu zYZIvlywv{~t)F+p8dJvMx{A=qOo#RlzhTjZ*2Sf5psXdq4ofY!#YMW%{FS6&V#njG zb?cy#@bcp}L7s-b+_uIY3zs|w&5s?X-upJq$szE{&V$=+T&9e#pMRvD!$Fj)QkkgOra)N z=WDirA17WF!tXH*Z8MOHyUS&(F!$^?T~a}{Pj?IHQV_AB`e}_^dCa0*3K8W?Gi5Lf zB#@UWEUPtV(!5l{qh2E- zQfn$u7T$LTbWN|=3RWeT?3cjZYR<% zEuTC7ued9ZhjM-Um7QY7SjNuSix^qPUY5x&%R$I8wDjiz_1X?_RS@{ z_C|9k9HmAN!ph28$a878+i39Cw;UIfKN47rEW_uLz_^jNwbS*MC|NWh(uQtOtAX}` zsA_DnIf9C6qK@xMEf~)};Adhga(Cb%71)hicx6Mn5mO%XB`+~ z-vkv!8j{v6*$vaqik0BHqCzfCXr{C)umH^@W3eQJH$M)1(L(e}zPWbr8;b$Q9d*I6 z$fRfYO5gQ*qBCo~Kwi#DixI_xT_dPJtuh8phh_!Pb+*UcgD3d4P|_hLOPvPksXRxk zy@Rp^)1}aLzJ0rZtI7Wg(Iq3SiRDknTt&EsrBiwDn`KO&TL;mqqY?0d15%pG;gYJi1kN+5@00i%(1e)_fv2PP zQuCFJdWP2y2U&&dG`AC~4{AhLC%P8Rt9uY2@fp>5Gjv9%E2Kzs5ef$KaFplQRH!ir zr#M||9<=a^E0Nlw_<{6WZS|7WXD?gb_=l*1ixb@WVJ%Qfj~GewU5&MxJ8Ltljw+o^ z`;cg5%&bL>h`XoL6A1TH@v0KjpjETaHgWb~>Qeld0o*+XWW*c#D2XE@JfDb?xGNH0 zJ0)Q@t9m@WzJ}0QtWv(Icx?vyP&L~30hUh~%{-h(HkG6#odU)iDX=z7(4nZ(B_MYd1NTQRl}v-)6;RUx66I z_NID961DqD7?iwoKn-s~I!S$fX)#aSV6a2_DlobAPoIUO*wk_na}LxWCsoS&mZPalTFaB#Xab*zP5cgan*T6yH=51ecAq#q>E z4Do$-7d2QJ%OJ}+uXWO9_d9Nsx8+G;K8!J!3D^%%{@9|y8)ABy%OW>7womhJyW}>a zrPBZTiMy3lLBZmnE?MrPl$3d*Zwia_%g3Vuu$4s?zd(^>(iD&T;T^j5laqKATDl^o zlY!T8%t+}vK@$0X=RG2a`hsnU7HThXSAs>JUQFnhSHCERY*6nSVm3+oa8xJXObf+I z=Cn61fXKWU5k^?##3jdTJ`VRED*vWLl50!cg6pg&Kg0etZ7YOHHxux{fv31K`atP< zvG{|=xpR}6K!J7ceev`vUa-WuoS(B9Q@iI@jZhm6yOZr=HhB4@tI z+^41QxuJ{qK8M)+`fqY@lv5-KJ3=aj7K*${+)$WK5Y~=Lv1d~6oKm|yDhy(OAeq0h z|4iG>!y{q5$klu6*^JP?)Srt|Cyk`YQ)Eiyk>Qv5VVj+SVk?4c@s^p|)?DIW`qrS| zJ_uD+uO&4+$~~WEB$Dyxv#pJW=C$<>?76(P86ao;X-8a?;v}#WrWYuQy^j#1kh!~A zwOKl}NZC*Z*Mt|hb@Kp1UU-`#2k+<-#9NZP)x-7qIq?*H-F4SrgvmdPJViNW!V;V` zg%_7i2r|BLe4GuIdO5e+`w^fyp__l&KEkrd(fFfb?1u29a7XU&j(bk93aD-`3_}~pF*mrZ}EtOx90lUp;x;icE|RB8TWa@`KVd)nDx^bNVS#~g8(4Zrmw)sFhs!wevjX#Bx~tjxmhu=Mpip0pQu z;>9}F)6kG|-?2ZYdi>BdqR|7K9bwn`2E#5@Db%ZLm$1VYbO|`LZl(4pIAH4ldeDe# z{CrCNYDHc1`cT?RUSxsrPaVk+M=BX~3zA7#kiqY(-4X9;``r-nuy0^FCtZLjA!yLD z-|BPq_{2PlqsM#t(~gSh(bPPd91?9pDMb*Ac+OsHyITK3~^; z=iy0b9Tj$Vi_R)Jm~nXpX>%p;b8t++!y8V)3&Dg1;mZ7#8`wm&hHujk*%rt$%8()7 zcxrX7YE|_i-8c15FeQV7YERhgbrvLXPJVbS@~8f}-NO)0RF8HYgP%^s-U^mU`-8>U zP;R$bvtu^wWR!95D<4bN%Vgu%=Lv}5yu&j(@8Ro~cupa7`il_M*l7#Gv@_Tk1$^gN zKO99)!zLv$&2P*F1$&Njd`g)muq{mus`YE!WOVBJ&Rf~Gqr#rs=l6PS=I^=xJ#xzB zTf)KzvnQVVwLh`IncFQ(nFZDNkZtagWQWoHKZI58!bw8Z*!|kozDF@|eExXcsrlym zD-VTtISsR&bGe6Sa>I8;pejp>u9ijewk>B*=m0taHxg5Nx>PUPa{9kv?Aec z>m)<-E$u{14=Po1%o6r<3Q=Qt>C>wc@2js-`ahvl5oWm7 zxgK&Z4DQHmNmAFVsguv_o*b8pYZzpifXOz-m`}yOUBN`n=xk)g9pQliJ;H$8&q!Jz zgY>r2b)#2M3HKaTn-E``B`o(S+7h;zn^DRsy!l@cwtsDGJ*{Jpi)2qYrAw{5U{6p2 zFRL*@*jM!(?m0An{NW>h35T+YBUG54S@LkKmP3FeL1Z2S5~4$Y_)_frW{tW)}dVC571#( z8dPv{ONg=1uP5f5X|V?R<}TU8<(OokD(MUKX7>J8H4@5pF~NMw_6Xw~t0C{pT64yx z))^HPS9-~FHb$r|R`B7hdLpJ=xKF3VG&hS2s#ahFNRH3sgx$TVMk7xnU2|{o3utFk zbL4}W9EW~e)ws!QHS;tBeB>Q}fj4qigoUt#^_*bS)M#kX9yHBxf1?B!d$%VLfjHGs z_F`?WVlK;eFDEBa%y-HCyE%>Sd~uO<02w$(cmCkgPM3g9&@TBJA{eE*F=BYt^-HiKD;$we2= zl&XSrh`WL@dnj7x`2r3B6E^cxulY^V!~gNiqX>BNAA+zN6J+>Hfc*zin#>)W-e?K9 z(v4v80M^R0V%z|n|Er+hVSB--dUix*l%-9G-u=th-Kl_H_VlFOx3W2=QGONc%beB# z>-pGefzyVTM6MO{tpLi8`U6t~dIA4qlyNv|z5l;QWjSUU9E}<%&pJU>ixn+P0D8AW z5UoN?iF`TO<+9#s;0+rE`I9~vr=cQC{7bo`&M@?u3--(rlZD~zjEEW{X)teKKL^8dmd_V4?rMlk z*QT|zlbN*v$VXAVwD+vO1^s7XF!-3s)PmvF{AIhs^<}Vi9J!ZS@d7HnW~(&V(6X3o z>l9?Jrpfvn(I7^Y?Cp)daMgu@6|(7#sz*+oAOc%NiqDpH1js8Z3<&}TsI;n3oH6Gp z!vo54HV4Ib-eL^SBhy@J_X8{G+@k<12abEEzrg$-y;(o@oddFC>wP=*-0@?;Wo&3+ JP@(4*^Iw|h0H6Q> literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/T0-fig-parameter-matching.png b/docs/source/tutorials/figures/T0-fig-parameter-matching.png new file mode 100644 index 0000000000000000000000000000000000000000..24013cc12a4014c650c6642b8a90ab650d37e561 GIT binary patch literal 95584 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

b=mWB%B<9I({`8aQAL)B9mdpY=Y$Ho4 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

1Y|ZyBV@Xvz#Z@P7bLVI*R89&da;HsATJJ_G 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 literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/T0-fig-trainer-and-evaluator.png b/docs/source/tutorials/figures/T0-fig-trainer-and-evaluator.png new file mode 100644 index 0000000000000000000000000000000000000000..38222ee8dccd69c402ab4aa343d0ad4e904a6935 GIT binary patch literal 71418 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

m(}x1|Z5_jDTLL{6J2UPvA{oc5&@eOhyqO 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 R0|Whu2}ui9@aug4{{T_1IOG5T literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/paddle-ernie-1.0-masking-levels.png b/docs/source/tutorials/figures/paddle-ernie-1.0-masking-levels.png new file mode 100644 index 0000000000000000000000000000000000000000..ff2519c4bc2c6b3ce4c63a7612fcc1e11f9cf4f8 GIT binary patch literal 59022 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 A2*un>rXm%)<3+ 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

JEb8#^WyOcnE_v`AmT$lo#M5@Z? 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

  • M;hg~qMEIz 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 literal 0 HcmV?d00001 diff --git a/docs/source/tutorials/figures/paddle-ernie-3.0-framework.png b/docs/source/tutorials/figures/paddle-ernie-3.0-framework.png new file mode 100644 index 0000000000000000000000000000000000000000..f50ddb1c51525dc33ff0c92806afba4a859456d8 GIT binary patch literal 202018 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%0AWo)}YUioHQF)xLgQQ`g3Vs#7I7rWx; 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 yFNBK`` 这个 token 得到足够的训练, diff --git a/fastNLP/transformers/__init__.py b/fastNLP/transformers/__init__.py index 3b375020..6b175b28 100644 --- a/fastNLP/transformers/__init__.py +++ b/fastNLP/transformers/__init__.py @@ -1,4 +1,3 @@ """ :mod:`transformers` 模块,包含了常用的预训练模型。 """ -import sphinx-multiversion \ No newline at end of file From 104db0ee1314c6eb7bc5c26fb47e576ecc2e1a93 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:41:24 +0000 Subject: [PATCH 05/14] rst --- docs/source/fastNLP.core.callbacks.rst | 1 + docs/source/fastNLP.core.collators.padders.rst | 1 + docs/source/fastNLP.core.dataloaders.rst | 2 +- docs/source/fastNLP.core.dataloaders.torch_dataloader.rst | 1 + docs/source/fastNLP.core.drivers.rst | 1 + docs/source/fastNLP.core.drivers.torch_driver.rst | 4 +++- docs/source/fastNLP.core.metrics.backend.rst | 1 + docs/source/fastNLP.core.utils.rst | 3 +++ docs/source/fastNLP.io.loader.rst | 1 - docs/source/fastNLP.io.pipe.rst | 1 - docs/source/fastNLP.io.rst | 1 - docs/source/fastNLP.modules.rst | 1 + docs/source/fastNLP.rst | 4 ++++ docs/source/fastNLP.transformers.rst | 3 +-- docs/source/fastNLP.transformers.torch.rst | 2 +- 15 files changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/source/fastNLP.core.callbacks.rst b/docs/source/fastNLP.core.callbacks.rst index 89d85f52..d0f3d210 100644 --- a/docs/source/fastNLP.core.callbacks.rst +++ b/docs/source/fastNLP.core.callbacks.rst @@ -31,5 +31,6 @@ Submodules fastNLP.core.callbacks.lr_scheduler_callback fastNLP.core.callbacks.more_evaluate_callback fastNLP.core.callbacks.progress_callback + fastNLP.core.callbacks.timer_callback fastNLP.core.callbacks.topk_saver fastNLP.core.callbacks.utils diff --git a/docs/source/fastNLP.core.collators.padders.rst b/docs/source/fastNLP.core.collators.padders.rst index 6f40becb..0c50dd4c 100644 --- a/docs/source/fastNLP.core.collators.padders.rst +++ b/docs/source/fastNLP.core.collators.padders.rst @@ -16,6 +16,7 @@ Submodules fastNLP.core.collators.padders.get_padder fastNLP.core.collators.padders.jittor_padder fastNLP.core.collators.padders.numpy_padder + fastNLP.core.collators.padders.oneflow_padder fastNLP.core.collators.padders.padder fastNLP.core.collators.padders.paddle_padder fastNLP.core.collators.padders.raw_padder diff --git a/docs/source/fastNLP.core.dataloaders.rst b/docs/source/fastNLP.core.dataloaders.rst index e8c6b799..db53dbe0 100644 --- a/docs/source/fastNLP.core.dataloaders.rst +++ b/docs/source/fastNLP.core.dataloaders.rst @@ -13,6 +13,7 @@ Subpackages :maxdepth: 4 fastNLP.core.dataloaders.jittor_dataloader + fastNLP.core.dataloaders.oneflow_dataloader fastNLP.core.dataloaders.paddle_dataloader fastNLP.core.dataloaders.torch_dataloader @@ -22,6 +23,5 @@ Submodules .. toctree:: :maxdepth: 4 - fastNLP.core.dataloaders.mix_dataloader fastNLP.core.dataloaders.prepare_dataloader fastNLP.core.dataloaders.utils diff --git a/docs/source/fastNLP.core.dataloaders.torch_dataloader.rst b/docs/source/fastNLP.core.dataloaders.torch_dataloader.rst index c9acca23..a3aeb1bf 100644 --- a/docs/source/fastNLP.core.dataloaders.torch_dataloader.rst +++ b/docs/source/fastNLP.core.dataloaders.torch_dataloader.rst @@ -13,3 +13,4 @@ Submodules :maxdepth: 4 fastNLP.core.dataloaders.torch_dataloader.fdl + fastNLP.core.dataloaders.torch_dataloader.mix_dataloader diff --git a/docs/source/fastNLP.core.drivers.rst b/docs/source/fastNLP.core.drivers.rst index bb168c76..30652fec 100644 --- a/docs/source/fastNLP.core.drivers.rst +++ b/docs/source/fastNLP.core.drivers.rst @@ -13,6 +13,7 @@ Subpackages :maxdepth: 4 fastNLP.core.drivers.jittor_driver + fastNLP.core.drivers.oneflow_driver fastNLP.core.drivers.paddle_driver fastNLP.core.drivers.torch_driver diff --git a/docs/source/fastNLP.core.drivers.torch_driver.rst b/docs/source/fastNLP.core.drivers.torch_driver.rst index 9a0109a2..c9080a86 100644 --- a/docs/source/fastNLP.core.drivers.torch_driver.rst +++ b/docs/source/fastNLP.core.drivers.torch_driver.rst @@ -13,9 +13,11 @@ Submodules :maxdepth: 4 fastNLP.core.drivers.torch_driver.ddp + fastNLP.core.drivers.torch_driver.deepspeed fastNLP.core.drivers.torch_driver.dist_utils - fastNLP.core.drivers.torch_driver.fairscale_sharded + fastNLP.core.drivers.torch_driver.fairscale fastNLP.core.drivers.torch_driver.initialize_torch_driver fastNLP.core.drivers.torch_driver.single_device fastNLP.core.drivers.torch_driver.torch_driver + fastNLP.core.drivers.torch_driver.torch_fsdp fastNLP.core.drivers.torch_driver.utils diff --git a/docs/source/fastNLP.core.metrics.backend.rst b/docs/source/fastNLP.core.metrics.backend.rst index 5a8cf4ad..4466a54a 100644 --- a/docs/source/fastNLP.core.metrics.backend.rst +++ b/docs/source/fastNLP.core.metrics.backend.rst @@ -13,6 +13,7 @@ Subpackages :maxdepth: 4 fastNLP.core.metrics.backend.jittor_backend + fastNLP.core.metrics.backend.oneflow_backend fastNLP.core.metrics.backend.paddle_backend fastNLP.core.metrics.backend.torch_backend diff --git a/docs/source/fastNLP.core.utils.rst b/docs/source/fastNLP.core.utils.rst index 2d682010..9bf76a23 100644 --- a/docs/source/fastNLP.core.utils.rst +++ b/docs/source/fastNLP.core.utils.rst @@ -16,7 +16,10 @@ Submodules fastNLP.core.utils.dummy_class fastNLP.core.utils.exceptions fastNLP.core.utils.jittor_utils + fastNLP.core.utils.oneflow_utils fastNLP.core.utils.paddle_utils fastNLP.core.utils.rich_progress + fastNLP.core.utils.seq_len_to_mask fastNLP.core.utils.torch_utils + fastNLP.core.utils.tqdm_progress fastNLP.core.utils.utils diff --git a/docs/source/fastNLP.io.loader.rst b/docs/source/fastNLP.io.loader.rst index bd91b795..20be532a 100644 --- a/docs/source/fastNLP.io.loader.rst +++ b/docs/source/fastNLP.io.loader.rst @@ -14,7 +14,6 @@ Submodules fastNLP.io.loader.classification fastNLP.io.loader.conll - fastNLP.io.loader.coreference fastNLP.io.loader.csv fastNLP.io.loader.cws fastNLP.io.loader.json diff --git a/docs/source/fastNLP.io.pipe.rst b/docs/source/fastNLP.io.pipe.rst index 9ad7e539..53a62918 100644 --- a/docs/source/fastNLP.io.pipe.rst +++ b/docs/source/fastNLP.io.pipe.rst @@ -15,7 +15,6 @@ Submodules fastNLP.io.pipe.classification fastNLP.io.pipe.conll fastNLP.io.pipe.construct_graph - fastNLP.io.pipe.coreference fastNLP.io.pipe.cws fastNLP.io.pipe.matching fastNLP.io.pipe.pipe diff --git a/docs/source/fastNLP.io.rst b/docs/source/fastNLP.io.rst index 5f025bba..7e1a5a67 100644 --- a/docs/source/fastNLP.io.rst +++ b/docs/source/fastNLP.io.rst @@ -25,5 +25,4 @@ Submodules fastNLP.io.embed_loader fastNLP.io.file_reader fastNLP.io.file_utils - fastNLP.io.model_io fastNLP.io.utils diff --git a/docs/source/fastNLP.modules.rst b/docs/source/fastNLP.modules.rst index fa1d95de..b686105d 100644 --- a/docs/source/fastNLP.modules.rst +++ b/docs/source/fastNLP.modules.rst @@ -13,3 +13,4 @@ Subpackages :maxdepth: 4 fastNLP.modules.mix_modules + fastNLP.modules.torch diff --git a/docs/source/fastNLP.rst b/docs/source/fastNLP.rst index 89c8e058..55776c22 100644 --- a/docs/source/fastNLP.rst +++ b/docs/source/fastNLP.rst @@ -13,6 +13,10 @@ Subpackages :maxdepth: 4 fastNLP.core + fastNLP.embeddings fastNLP.envs fastNLP.io + fastNLP.models fastNLP.modules + .. 以下为手动添加 + fastNLP.transformers \ No newline at end of file diff --git a/docs/source/fastNLP.transformers.rst b/docs/source/fastNLP.transformers.rst index c681acca..023da63d 100644 --- a/docs/source/fastNLP.transformers.rst +++ b/docs/source/fastNLP.transformers.rst @@ -1,6 +1,5 @@ fastNLP.transformers package -======================= - +============================ .. automodule:: fastNLP.transformers :members: :undoc-members: diff --git a/docs/source/fastNLP.transformers.torch.rst b/docs/source/fastNLP.transformers.torch.rst index ab6ef210..29080d73 100644 --- a/docs/source/fastNLP.transformers.torch.rst +++ b/docs/source/fastNLP.transformers.torch.rst @@ -1,5 +1,5 @@ fastNLP.transformers.torch package -======================= +============================= .. automodule:: fastNLP.transformers.torch :members: From 869a522cbc5244cf77c3013cb63539c309bfd616 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 11:51:57 +0000 Subject: [PATCH 06/14] update conf.py --- docs/source/conf.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 01884ef7..812fb0ec 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,9 +24,9 @@ copyright = '2022, fastNLP' author = 'fastNLP' # The short X.Y version -version = '0.8' +version = '1.0' # The full version, including alpha/beta/rc tags -release = '0.8.0' +release = '1.0.0-alpha' # -- General configuration --------------------------------------------------- @@ -45,6 +45,7 @@ extensions = [ 'sphinx.ext.todo', 'sphinx_autodoc_typehints', 'sphinx_multiversion', + 'nbsphinx', ] autodoc_default_options = { @@ -169,7 +170,7 @@ man_pages = [ # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'fastNLP', 'fastNLP Documentation', - author, 'fastNLP', 'One line description of project.', + author, 'fastNLP', 'A fast NLP tool for programming.', 'Miscellaneous'), ] From 348107978eea3c2b2bb35e816c3d19aa16035fe8 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 13:55:12 +0000 Subject: [PATCH 07/14] =?UTF-8?q?fastNLP/io/pipe=20=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/fastNLP.io.loader.conll.rst | 7 - docs/source/fastNLP.io.loader.coreference.rst | 7 - docs/source/fastNLP.transformers.torch.rst | 2 +- fastNLP/core/callbacks/callback_event.py | 30 +- fastNLP/io/__init__.py | 2 +- fastNLP/io/pipe/__init__.py | 4 +- fastNLP/io/pipe/classification.py | 32 +-- fastNLP/io/pipe/conll.py | 12 +- fastNLP/io/pipe/construct_graph.py | 12 +- fastNLP/io/pipe/cws.py | 43 ++- fastNLP/io/pipe/matching.py | 257 ++++++++++++------ fastNLP/io/pipe/pipe.py | 27 +- fastNLP/io/pipe/qa.py | 36 +-- fastNLP/io/pipe/summarization.py | 44 +-- fastNLP/io/pipe/utils.py | 18 +- 15 files changed, 285 insertions(+), 248 deletions(-) delete mode 100644 docs/source/fastNLP.io.loader.conll.rst delete mode 100644 docs/source/fastNLP.io.loader.coreference.rst diff --git a/docs/source/fastNLP.io.loader.conll.rst b/docs/source/fastNLP.io.loader.conll.rst deleted file mode 100644 index 96123649..00000000 --- a/docs/source/fastNLP.io.loader.conll.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.io.loader.conll module -============================== - -.. automodule:: fastNLP.io.loader.conll - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/fastNLP.io.loader.coreference.rst b/docs/source/fastNLP.io.loader.coreference.rst deleted file mode 100644 index 58dfb880..00000000 --- a/docs/source/fastNLP.io.loader.coreference.rst +++ /dev/null @@ -1,7 +0,0 @@ -fastNLP.io.loader.coreference module -==================================== - -.. automodule:: fastNLP.io.loader.coreference - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/fastNLP.transformers.torch.rst b/docs/source/fastNLP.transformers.torch.rst index 29080d73..9d5f0d65 100644 --- a/docs/source/fastNLP.transformers.torch.rst +++ b/docs/source/fastNLP.transformers.torch.rst @@ -1,5 +1,5 @@ fastNLP.transformers.torch package -============================= +================================== .. automodule:: fastNLP.transformers.torch :members: diff --git a/fastNLP/core/callbacks/callback_event.py b/fastNLP/core/callbacks/callback_event.py index 8a51b6de..f632cf3c 100644 --- a/fastNLP/core/callbacks/callback_event.py +++ b/fastNLP/core/callbacks/callback_event.py @@ -35,14 +35,14 @@ class Event: :param value: Trainer 的 callback 时机; :param every: 每触发多少次才真正运行一次; - :param once: 在第一次运行后时候再次执行; + :param once: 是否仅运行一次; :param filter_fn: 输入参数的应该为 ``(filter, trainer)``,其中 ``filter`` 对象中包含了 `filter.num_called` 和 `filter.num_executed` 两个变量分别获取当前被调用了多少次,真正执行了多少次;``trainer`` 对象即为当前正在运行的 Trainer; """ every: Optional[int] - once: Optional[int] + once: Optional[bool] - def __init__(self, value: str, every: Optional[int] = None, once: Optional[int] = None, + def __init__(self, value: str, every: Optional[int] = None, once: Optional[bool] = None, filter_fn: Optional[Callable] = None): self.every = every self.once = once @@ -68,7 +68,6 @@ class Event: return Event(value='on_after_trainer_initialized', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_sanity_check_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_sanity_check_begin` 时触发; @@ -85,7 +84,6 @@ class Event: return Event(value='on_sanity_check_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_sanity_check_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_sanity_check_end` 时触发; @@ -101,7 +99,6 @@ class Event: return Event(value='on_sanity_check_end', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_begin` 时触发; @@ -117,7 +114,6 @@ class Event: return Event(value='on_train_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_end` 时触发; @@ -133,7 +129,6 @@ class Event: return Event(value='on_train_end', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_epoch_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_epoch_begin` 时触发; @@ -149,7 +144,6 @@ class Event: return Event(value='on_train_epoch_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_epoch_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_epoch_end` 时触发; @@ -165,7 +159,6 @@ class Event: return Event(value='on_train_epoch_end', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_fetch_data_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_fetch_data_begin` 时触发; @@ -181,7 +174,6 @@ class Event: return Event(value='on_fetch_data_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_fetch_data_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_fetch_data_end` 时触发; @@ -197,7 +189,6 @@ class Event: return Event(value='on_fetch_data_end', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_batch_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_batch_begin` 时触发; @@ -213,7 +204,6 @@ class Event: return Event(value='on_train_batch_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_train_batch_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_train_batch_end` 时触发; @@ -229,7 +219,6 @@ class Event: return Event(value='on_train_batch_end', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_exception(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_exception` 时触发; @@ -245,7 +234,6 @@ class Event: return Event(value='on_exception', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_save_model(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_save_model` 时触发; @@ -261,7 +249,6 @@ class Event: return Event(value='on_save_model', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_load_model(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_load_model` 时触发; @@ -277,7 +264,6 @@ class Event: return Event(value='on_load_model', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_save_checkpoint(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_save_checkpoint` 时触发; @@ -293,7 +279,6 @@ class Event: return Event(value='on_save_checkpoint', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_load_checkpoint(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_load_checkpoint` 时触发; @@ -309,7 +294,6 @@ class Event: return Event(value='on_load_checkpoint', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_load_checkpoint(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_load_checkpoint` 时触发; @@ -325,7 +309,6 @@ class Event: return Event(value='on_load_checkpoint', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_before_backward(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_before_backward` 时触发; @@ -341,7 +324,6 @@ class Event: return Event(value='on_before_backward', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_after_backward(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_after_backward` 时触发; @@ -357,7 +339,6 @@ class Event: return Event(value='on_after_backward', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_before_optimizers_step(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_before_optimizers_step` 时触发; @@ -373,7 +354,6 @@ class Event: return Event(value='on_before_optimizers_step', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_after_optimizers_step(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_after_optimizers_step` 时触发; @@ -389,7 +369,6 @@ class Event: return Event(value='on_after_optimizers_step', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_before_zero_grad(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_before_zero_grad` 时触发; @@ -405,7 +384,6 @@ class Event: return Event(value='on_before_zero_grad', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_after_zero_grad(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_after_zero_grad` 时触发; @@ -421,7 +399,6 @@ class Event: return Event(value='on_after_zero_grad', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_evaluate_begin(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_evaluate_begin` 时触发; @@ -437,7 +414,6 @@ class Event: return Event(value='on_evaluate_begin', every=every, once=once, filter_fn=filter_fn) @staticmethod - def on_evaluate_end(every=None, once=None, filter_fn=None): """ 当 Trainer 运行到 :func:`on_evaluate_end` 时触发; diff --git a/fastNLP/io/__init__.py b/fastNLP/io/__init__.py index e525fee2..c4fa600e 100644 --- a/fastNLP/io/__init__.py +++ b/fastNLP/io/__init__.py @@ -105,7 +105,7 @@ __all__ = [ "BQCorpusPipe", "RenamePipe", "GranularizePipe", - "MachingTruncatePipe", + "TruncateBertPipe", "CMRC2018BertPipe", diff --git a/fastNLP/io/pipe/__init__.py b/fastNLP/io/pipe/__init__.py index 05a82806..e7314e00 100644 --- a/fastNLP/io/pipe/__init__.py +++ b/fastNLP/io/pipe/__init__.py @@ -52,7 +52,7 @@ __all__ = [ "BQCorpusPipe", "RenamePipe", "GranularizePipe", - "MachingTruncatePipe", + "TruncateBertPipe", "CMRC2018BertPipe", @@ -74,7 +74,7 @@ from .conll import Conll2003Pipe, iob2, iob2bioes from .cws import CWSPipe from .matching import MatchingBertPipe, RTEBertPipe, SNLIBertPipe, QuoraBertPipe, QNLIBertPipe, MNLIBertPipe, \ MatchingPipe, RTEPipe, SNLIPipe, QuoraPipe, QNLIPipe, MNLIPipe, CNXNLIBertPipe, CNXNLIPipe, BQCorpusBertPipe, \ - LCQMCPipe, BQCorpusPipe, LCQMCBertPipe, RenamePipe, GranularizePipe, MachingTruncatePipe + LCQMCPipe, BQCorpusPipe, LCQMCBertPipe, RenamePipe, GranularizePipe, TruncateBertPipe from .pipe import Pipe from .qa import CMRC2018BertPipe diff --git a/fastNLP/io/pipe/classification.py b/fastNLP/io/pipe/classification.py index 54df7d00..7527a3d6 100644 --- a/fastNLP/io/pipe/classification.py +++ b/fastNLP/io/pipe/classification.py @@ -94,7 +94,7 @@ class CLSBasePipe(Pipe): def process_from_file(self, paths) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -154,7 +154,7 @@ class YelpFullPipe(CLSBasePipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -184,7 +184,7 @@ class YelpPolarityPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -214,7 +214,7 @@ class AGsNewsPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -244,7 +244,7 @@ class DBPediaPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -328,7 +328,7 @@ class SSTPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -358,7 +358,7 @@ class SST2Pipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -421,7 +421,7 @@ class IMDBPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -518,7 +518,7 @@ class ChnSentiCorpPipe(Pipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -622,7 +622,7 @@ class THUCNewsPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -713,7 +713,7 @@ class WeiboSenti100kPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -737,7 +737,7 @@ class MRPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -763,7 +763,7 @@ class R8Pipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -789,7 +789,7 @@ class R52Pipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -815,7 +815,7 @@ class OhsumedPipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -841,7 +841,7 @@ class NG20Pipe(CLSBasePipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/conll.py b/fastNLP/io/pipe/conll.py index 3e4dceed..d2d4730e 100644 --- a/fastNLP/io/pipe/conll.py +++ b/fastNLP/io/pipe/conll.py @@ -104,7 +104,7 @@ class Conll2003NERPipe(_NERPipe): def process_from_file(self, paths) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -193,7 +193,7 @@ class Conll2003Pipe(Pipe): def process_from_file(self, paths): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -221,7 +221,7 @@ class OntoNotesNERPipe(_NERPipe): def process_from_file(self, paths): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -343,7 +343,7 @@ class MsraNERPipe(_CNNERPipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -379,7 +379,7 @@ class PeopleDailyPipe(_CNNERPipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -415,7 +415,7 @@ class WeiboNERPipe(_CNNERPipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/construct_graph.py b/fastNLP/io/pipe/construct_graph.py index ebb0315a..26846002 100644 --- a/fastNLP/io/pipe/construct_graph.py +++ b/fastNLP/io/pipe/construct_graph.py @@ -164,7 +164,7 @@ class GraphBuilderBase: def build_graph_from_file(self, path: str): r""" - 传入文件路径,生成处理好的scipy_sparse_matrix对象。paths支持的路径形式可以参考 ::meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的scipy_sparse_matrix对象。paths支持的路径形式可以参考 ::meth:`fastNLP.io.Loader.load` :param path: :return: scipy_sparse_matrix @@ -185,7 +185,7 @@ class MRPmiGraphPipe(GraphBuilderBase): def build_graph(self, data_bundle: DataBundle): r""" - :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象。 :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) @@ -219,7 +219,7 @@ class R8PmiGraphPipe(GraphBuilderBase): def build_graph(self, data_bundle: DataBundle): r""" - :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象。 :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) @@ -253,7 +253,7 @@ class R52PmiGraphPipe(GraphBuilderBase): def build_graph(self, data_bundle: DataBundle): r""" - :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象。 :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) @@ -287,7 +287,7 @@ class OhsumedPmiGraphPipe(GraphBuilderBase): def build_graph(self, data_bundle: DataBundle): r""" - :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象。 :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) @@ -321,7 +321,7 @@ class NG20PmiGraphPipe(GraphBuilderBase): def build_graph(self, data_bundle: DataBundle): r""" - :param data_bundle: 需要处理的 :class:`fastNLP.io.DataBundle` 对象。 + :param data_bundle: 需要处理的 :class:`~fastNLP.io.DataBundle` 对象。 :return: 返回 ``csr`` 类型的稀疏矩阵图;包含训练集,验证集,测试集,在图中的 index 。 """ self._get_doc_edge(data_bundle) diff --git a/fastNLP/io/pipe/cws.py b/fastNLP/io/pipe/cws.py index 0afc9851..27068348 100644 --- a/fastNLP/io/pipe/cws.py +++ b/fastNLP/io/pipe/cws.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "CWSPipe" ] @@ -135,7 +133,7 @@ def _find_and_replace_digit_spans(line): class CWSPipe(Pipe): r""" - 对CWS数据进行预处理, 处理之后的数据,具备以下的结构 + 对 **CWS** 数据进行处理,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words", "chars", "target", "seq_len" @@ -144,30 +142,21 @@ class CWSPipe(Pipe): "2001年 新年 钟声...", "[8, 9, 9, 7, ...]", "[0, 1, 1, 1, 2...]", 20 "...", "[...]","[...]", . - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+-----------+-------+--------+---------+ - | field_names | raw_words | chars | target | seq_len | - +-------------+-----------+-------+--------+---------+ - | is_input | False | True | True | True | - | is_target | False | False | True | True | - | ignore_type | | False | False | False | - | pad_value | | 0 | 0 | 0 | - +-------------+-----------+-------+--------+---------+ - + :param dataset_name: data 的名称,支持 ``['pku', 'msra', 'cityu'(繁体), 'as'(繁体), None]`` + :param encoding_type: ``target`` 列使用什么类型的 encoding 方式,支持 ``['bmes', 'segapp']`` 两种。``"我 来自 复旦大学..."`` 这句话 ``bmes``的 + tag为 ``[S, B, E, B, M, M, E...]`` ; ``segapp`` 的 tag 为 ``[seg, app, seg, app, app, app, seg, ...]`` 。 + :param replace_num_alpha: 是否将数字和字母用特殊字符替换。 + :param bigrams: 是否增加一列 ``bigrams`` 。 ``bigrams`` 会对原文进行如下转化: ``['复', '旦', '大', '学', ...]->["复旦", "旦大", ...]`` 。如果 + 设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``bigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('bigrams')`` 获取。 + :param trigrams: 是否增加一列 ``trigrams`` 。 ``trigrams`` 会对原文进行如下转化 ``['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...]`` 。 + 如果设置为 ``True`` ,返回的 :class:`~fastNLP.core.DataSet` 将有一列名为 ``trigrams`` ,且已经转换为了 index 并设置为 input,对应的词表可以通过 + ``data_bundle.get_vocab('trigrams')`` 获取。 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, dataset_name=None, encoding_type='bmes', replace_num_alpha=True, - bigrams=False, trigrams=False, num_proc: int = 0): - r""" - - :param str,None dataset_name: 支持'pku', 'msra', 'cityu', 'as', None - :param str encoding_type: 可以选择'bmes', 'segapp'两种。"我 来自 复旦大学...", bmes的tag为[S, B, E, B, M, M, E...]; segapp - 的tag为[seg, app, seg, app, app, app, seg, ...] - :param bool replace_num_alpha: 是否将数字和字母用特殊字符替换。 - :param bool bigrams: 是否增加一列bigram. bigram的构成是['复', '旦', '大', '学', ...]->["复旦", "旦大", ...] - :param bool trigrams: 是否增加一列trigram. trigram的构成是 ['复', '旦', '大', '学', ...]->["复旦大", "旦大学", ...] - """ + def __init__(self, dataset_name: str=None, encoding_type: str='bmes', replace_num_alpha: bool=True, + bigrams: bool=False, trigrams: bool=False, num_proc: int = 0): if encoding_type == 'bmes': self.word_lens_to_tags = _word_lens_to_bmes else: @@ -220,7 +209,7 @@ class CWSPipe(Pipe): def process(self, data_bundle: DataBundle) -> DataBundle: r""" - 可以处理的DataSet需要包含raw_words列 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该包含 ``raw_words`` : .. csv-table:: :header: "raw_words" @@ -276,7 +265,7 @@ class CWSPipe(Pipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/matching.py b/fastNLP/io/pipe/matching.py index ecaace9d..a9abd943 100644 --- a/fastNLP/io/pipe/matching.py +++ b/fastNLP/io/pipe/matching.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "MatchingBertPipe", "RTEBertPipe", @@ -21,7 +19,7 @@ __all__ = [ "BQCorpusPipe", "RenamePipe", "GranularizePipe", - "MachingTruncatePipe", + "TruncateBertPipe", ] from functools import partial @@ -31,14 +29,13 @@ from .utils import get_tokenizer from ..data_bundle import DataBundle from ..loader.matching import SNLILoader, MNLILoader, QNLILoader, RTELoader, QuoraLoader, BQCorpusLoader, CNXNLILoader, \ LCQMCLoader -# from ...core._logger import log # from ...core.const import Const from ...core.vocabulary import Vocabulary class MatchingBertPipe(Pipe): r""" - Matching任务的Bert pipe,输出的DataSet将包含以下的field + **Matching** 任务的 Bert pipe ,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words1", "raw_words2", "target", "words", "seq_len" @@ -47,29 +44,17 @@ class MatchingBertPipe(Pipe): "This site includes a...", "The Government Executive...", 0, "[11, 12, 13,...]", 5 "...", "...", ., "[...]", . - words列是将raw_words1(即premise), raw_words2(即hypothesis)使用"[SEP]"链接起来转换为index的。 - words列被设置为input,target列被设置为target和input(设置为input以方便在forward函数中计算loss, - 如果不在forward函数中计算loss也不影响,fastNLP将根据forward函数的形参名进行传参). - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+------------+------------+--------+-------+---------+ - | field_names | raw_words1 | raw_words2 | target | words | seq_len | - +-------------+------------+------------+--------+-------+---------+ - | is_input | False | False | False | True | True | - | is_target | False | False | True | False | False | - | ignore_type | | | False | False | False | - | pad_value | | | 0 | 0 | 0 | - +-------------+------------+------------+--------+-------+---------+ + ``words`` 列是将 ``raw_words1`` (即 ``premise`` ), ``raw_words2`` (即 ``hypothesis`` )使用 ``[SEP]`` + 链接起来转换为 index 的。``words`` 列被设置为 input, ``target`` 列被设置为 target 和 input (设置为 input 以 + 方便在 :func:`forward` 函数中计算 loss,如果不在也不影响, **fastNLP** 将根据 :func:`forward` 函数的形参名进行 + 传参)。 + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, lower=False, tokenizer: str = 'raw', num_proc: int = 0): - r""" - - :param bool lower: 是否将word小写化。 - :param str tokenizer: 使用什么tokenizer来将句子切分为words. 支持spacy, raw两种。raw即使用空格拆分。 - """ super().__init__() self.lower = bool(lower) @@ -89,9 +74,9 @@ class MatchingBertPipe(Pipe): dataset.apply_field(self.tokenizer, field_name=field_name, new_field_name=new_field_name, num_proc=self.num_proc) return data_bundle - def process(self, data_bundle): + def process(self, data_bundle: DataBundle): r""" - 输入的data_bundle中的dataset需要具有以下结构: + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备以下结构: .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -100,7 +85,7 @@ class MatchingBertPipe(Pipe): "...","..." :param data_bundle: - :return: + :return: 处理后的 ``data_bundle`` """ for dataset in data_bundle.datasets.values(): if dataset.has_field('target'): @@ -164,9 +149,16 @@ class MatchingBertPipe(Pipe): class RTEBertPipe(MatchingBertPipe): + """ + 处理 **RTE** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -176,9 +168,16 @@ class RTEBertPipe(MatchingBertPipe): class SNLIBertPipe(MatchingBertPipe): + """ + 处理 **SNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -188,9 +187,16 @@ class SNLIBertPipe(MatchingBertPipe): class QuoraBertPipe(MatchingBertPipe): + """ + 处理 **Quora** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -200,9 +206,16 @@ class QuoraBertPipe(MatchingBertPipe): class QNLIBertPipe(MatchingBertPipe): + """ + 处理 **QNNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -212,9 +225,16 @@ class QNLIBertPipe(MatchingBertPipe): class MNLIBertPipe(MatchingBertPipe): + """ + 处理 **MNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -225,7 +245,7 @@ class MNLIBertPipe(MatchingBertPipe): class MatchingPipe(Pipe): r""" - Matching任务的Pipe。输出的DataSet将包含以下的field + **Matching** 任务的 Pipe,处理之后 :class:`~fastNLP.core.DataSet` 中的内容如下: .. csv-table:: :header: "raw_words1", "raw_words2", "target", "words1", "words2", "seq_len1", "seq_len2" @@ -234,21 +254,14 @@ class MatchingPipe(Pipe): "This site includes a...", "The Government Executive...", 0, "[11, 12, 13,...]", "[2, 7, ...]", 6, 7 "...", "...", ., "[...]", "[...]", ., . - words1是premise,words2是hypothesis。其中words1,words2,seq_len1,seq_len2被设置为input;target被设置为target - 和input(设置为input以方便在forward函数中计算loss,如果不在forward函数中计算loss也不影响,fastNLP将根据forward函数 - 的形参名进行传参)。 - - dataset的print_field_meta()函数输出的各个field的被设置成input和target的情况为:: - - +-------------+------------+------------+--------+--------+--------+----------+----------+ - | field_names | raw_words1 | raw_words2 | target | words1 | words2 | seq_len1 | seq_len2 | - +-------------+------------+------------+--------+--------+--------+----------+----------+ - | is_input | False | False | False | True | True | True | True | - | is_target | False | False | True | False | False | False | False | - | ignore_type | | | False | False | False | False | False | - | pad_value | | | 0 | 0 | 0 | 0 | 0 | - +-------------+------------+------------+--------+--------+--------+----------+----------+ + ``words1`` 是 ``premise`` ,``words2`` 是 ``hypothesis`` 。其中 ``words1`` , ``words2`` , ``seq_len1``, ``seq_len2`` + 被设置为 input; ``target`` 列被设置为 target 和 input (设置为 input 以 + 方便在 :func:`forward` 函数中计算 loss,如果不在也不影响, **fastNLP** 将根据 :func:`forward` 函数的形参名进行 + 传参)。 + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 """ def __init__(self, lower=False, tokenizer: str = 'raw', num_proc: int = 0): @@ -276,9 +289,9 @@ class MatchingPipe(Pipe): dataset.apply_field(self.tokenizer, field_name=field_name, new_field_name=new_field_name, num_proc=self.num_proc) return data_bundle - def process(self, data_bundle): + def process(self, data_bundle: DataBundle): r""" - 接受的DataBundle中的DataSet应该具有以下的field, target列可以没有 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备以下结构,可以没有 ``target`` 列: .. csv-table:: :header: "raw_words1", "raw_words2", "target" @@ -287,8 +300,8 @@ class MatchingPipe(Pipe): "This site includes a...", "The Government Executive...", "not_entailment" "...", "..." - :param ~fastNLP.DataBundle data_bundle: 通过loader读取得到的data_bundle,里面包含了数据集的原始数据内容 - :return: data_bundle + :param data_bundle: + :return: 处理后的 ``data_bundle`` """ data_bundle = self._tokenize(data_bundle, ['raw_words1', 'raw_words2'], ['words1', 'words2']) @@ -337,9 +350,16 @@ class MatchingPipe(Pipe): class RTEPipe(MatchingPipe): + """ + 处理 **RTE** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -349,9 +369,16 @@ class RTEPipe(MatchingPipe): class SNLIPipe(MatchingPipe): + """ + 处理 **SNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -361,9 +388,16 @@ class SNLIPipe(MatchingPipe): class QuoraPipe(MatchingPipe): + """ + 处理 **Quora** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -373,9 +407,16 @@ class QuoraPipe(MatchingPipe): class QNLIPipe(MatchingPipe): + """ + 处理 **QNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -385,9 +426,16 @@ class QNLIPipe(MatchingPipe): class MNLIPipe(MatchingPipe): + """ + 处理 **MNLI** 数据。 + + :param lower: 是否对输入进行小写化。 + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['spacy', 'raw']`` 。``'raw'`` 表示使用空格作为切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -397,12 +445,18 @@ class MNLIPipe(MatchingPipe): class LCQMCPipe(MatchingPipe): - def __init__(self, tokenizer='cn=char', num_proc=0): + """ + 处理 **LCQMC** 数据。 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -415,12 +469,18 @@ class LCQMCPipe(MatchingPipe): class CNXNLIPipe(MatchingPipe): + """ + 处理 **XNLI Chinese** 数据。 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -434,12 +494,18 @@ class CNXNLIPipe(MatchingPipe): class BQCorpusPipe(MatchingPipe): + """ + 处理 **BQ Corpus** 数据。 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -452,6 +518,13 @@ class BQCorpusPipe(MatchingPipe): class RenamePipe(Pipe): + """ + 重命名数据集的 Pipe ,经过处理后会将数据集中的 ``chars``, ``raw_chars1`` 等列重命名为 ``words``, + ``raw_words1``,反之亦然。 + + :param task: 任务类型,可选 ``['cn-nli', 'cn-nli-bert']`` 。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, task='cn-nli', num_proc=0): super().__init__() self.task = task @@ -459,7 +532,7 @@ class RenamePipe(Pipe): def process(self, data_bundle: DataBundle): # rename field name for Chinese Matching dataset """ - + :param data_bundle: :return: 处理后的 ``data_bundle`` """ if (self.task == 'cn-nli'): @@ -497,6 +570,16 @@ class RenamePipe(Pipe): class GranularizePipe(Pipe): + """ + 将数据集中 ``target`` 列中的 tag 按照一定的映射进行重命名,并丢弃不在映射中的 tag。 + + :param task: 任务类型,目前仅支持 ``['XNLI']``。 + + - ``'XNLI'`` -- 将 ``neutral``, ``entailment``, ``contradictory``, ``contradiction`` 分别 + 映射为 0, 1, 2, 3; + + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, task=None, num_proc=0): super().__init__() self.task = task @@ -520,7 +603,7 @@ class GranularizePipe(Pipe): def process(self, data_bundle: DataBundle): """ - + :param data_bundle: :return: 处理后的 ``data_bundle`` """ task_tag_dict = { @@ -532,28 +615,19 @@ class GranularizePipe(Pipe): raise RuntimeError(f"Only support {task_tag_dict.keys()} task_tag_map.") return data_bundle - -class MachingTruncatePipe(Pipe): # truncate sentence for bert, modify seq_len - def __init__(self): - super().__init__() - - def process(self, data_bundle: DataBundle): - """ - - :return: None - """ - for name, dataset in data_bundle.datasets.items(): - pass - return None - - class LCQMCBertPipe(MatchingBertPipe): - def __init__(self, tokenizer='cn=char', num_proc=0): + """ + 处理 **LCQMC** 数据 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ + def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -567,12 +641,18 @@ class LCQMCBertPipe(MatchingBertPipe): class BQCorpusBertPipe(MatchingBertPipe): + """ + 处理 **BQ Corpus** 数据。 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -586,12 +666,18 @@ class BQCorpusBertPipe(MatchingBertPipe): class CNXNLIBertPipe(MatchingBertPipe): + """ + 处理 **XNLI Chinese** 数据。 + + :param tokenizer: 使用哪种 tokenize 方式将数据切成单词。支持 ``['cn-char']`` ,按字分词。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, tokenizer='cn-char', num_proc=0): super().__init__(tokenizer=tokenizer, num_proc=num_proc) def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: @@ -606,6 +692,13 @@ class CNXNLIBertPipe(MatchingBertPipe): class TruncateBertPipe(Pipe): + """ + 对数据进行截断的 **Pipe** 。该 **Pipe** 将会寻找每条数据中的第一个分隔符 ``[SEP]`` ,对其前后的数据分别进行截断。 + 对于中文任务会将前后的文本分别截断至长度 **250** ,对于英文任务会分别截断至 **215** 。 + + :param task: 任务类型,可选 ``['cn', 'en']`` ,分别表示 **中文任务** 和 **英文任务** 。 + :param num_proc: 处理数据时使用的进程数目。 + """ def __init__(self, task='cn', num_proc=0): super().__init__() self.task = task @@ -631,7 +724,7 @@ class TruncateBertPipe(Pipe): def process(self, data_bundle: DataBundle) -> DataBundle: """ - + :param data_bundle: :return: 处理后的 ``data_bundle`` """ for name in data_bundle.datasets.keys(): diff --git a/fastNLP/io/pipe/pipe.py b/fastNLP/io/pipe/pipe.py index 68106c17..0ee43ae8 100644 --- a/fastNLP/io/pipe/pipe.py +++ b/fastNLP/io/pipe/pipe.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "Pipe", ] @@ -9,31 +7,36 @@ from fastNLP.io.data_bundle import DataBundle class Pipe: r""" - Pipe是fastNLP中用于处理DataBundle的类,但实际是处理DataBundle中的DataSet。所有Pipe都会在其process()函数的文档中指出该Pipe可处理的DataSet应该具备怎样的格式;在Pipe - 文档中说明该Pipe返回后DataSet的格式以及其field的信息;以及新增的Vocabulary的信息。 + :class:`Pipe` 是 **fastNLP** 中用于处理 :class:`~fastNLP.io.DataBundle` 的类,但实际是处理其中的 :class:`~fastNLP.core.DataSet` 。 + 所有 ``Pipe`` 都会在其 :meth:`process` 函数的文档中指出该 ``Pipe`` 可处理的 :class:`~fastNLP.core.DataSet` 应该具备怎样的格式;在 + ``Pipe`` 文档中说明该 ``Pipe`` 返回后 :class:`~fastNLP.core.DataSet` 的格式以及其 field 的信息;以及新增的 :class:`~fastNLP.core.Vocabulary` + 的信息。 - 一般情况下Pipe处理包含以下的几个过程,(1)将raw_words或raw_chars进行tokenize以切分成不同的词或字; - (2) 再建立词或字的 :class:`~fastNLP.Vocabulary` , 并将词或字转换为index; (3)将target列建立词表并将target列转为index; + 一般情况下 **Pipe** 处理包含以下的几个过程: + + 1. 将 ``raw_words`` 或 ``raw_chars`` 进行 tokenize 以切分成不同的词或字; + 2. 建立词或字的 :class:`~fastNLP.core.Vocabulary` ,并将词或字转换为 index; + 3. 将 ``target`` 列建立词表并将 ``target`` 列转为 index; - Pipe中提供了两个方法 + **Pipe** 中提供了两个方法: - -process()函数,输入为DataBundle - -process_from_file()函数,输入为对应Loader的load函数可接受的类型。 + - :meth:`process` 函数,输入为 :class:`~fastNLP.io.DataBundle` + - :meth:`process_from_file` 函数,输入为对应 :meth:`fastNLP.io.Loader.load` 函数可接受的类型。 """ def process(self, data_bundle: DataBundle) -> DataBundle: r""" - 对输入的DataBundle进行处理,然后返回该DataBundle。 + 对输入的 ``data_bundle`` 进行处理,然后返回该 ``data_bundle`` - :param ~fastNLP.DataBundle data_bundle: 需要处理的DataBundle对象 + :param data_bundle: :return: 处理后的 ``data_bundle`` """ raise NotImplementedError def process_from_file(self, paths: str) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/qa.py b/fastNLP/io/pipe/qa.py index 2deb4085..0d646263 100644 --- a/fastNLP/io/pipe/qa.py +++ b/fastNLP/io/pipe/qa.py @@ -1,5 +1,5 @@ r""" -本文件中的Pipe主要用于处理问答任务的数据。 +本文件中的 **Pipe** 主要用于处理问答任务的数据。 """ @@ -78,32 +78,20 @@ def _concat_clip(data_bundle, max_len, concat_field_name='raw_chars'): class CMRC2018BertPipe(Pipe): r""" - 处理之后的DataSet将新增以下的field(传入的field仍然保留) + 处理 **CMRC2018** 的数据,处理之后 :class:`~fastNLP.core.DataSet` 中新增的内容如下(原有的 field 仍然保留): .. csv-table:: :header: "context_len", "raw_chars", "target_start", "target_end", "chars" - 492, ['范', '廷', '颂... ], 30, 34, "[21, 25, ...]" - 491, ['范', '廷', '颂... ], 41, 61, "[21, 25, ...]" - + 492, "['范', '廷', '颂... ]", 30, 34, "[21, 25, ...]" + 491, "['范', '廷', '颂... ]", 41, 61, "[21, 25, ...]" ".", "...", "...","...", "..." - raw_words列是context与question拼起来的结果(连接的地方加入了[SEP]),words是转为index的值, target_start为答案start的index,target_end为答案end的index - (闭区间);context_len指示的是words列中context的长度。 - - 其中各列的meta信息如下: - - .. code:: - - +-------------+-------------+-----------+--------------+------------+-------+---------+ - | field_names | context_len | raw_chars | target_start | target_end | chars | answers | - +-------------+-------------+-----------+--------------+------------+-------+---------| - | is_input | False | False | False | False | True | False | - | is_target | True | True | True | True | False | True | - | ignore_type | False | True | False | False | False | True | - | pad_value | 0 | 0 | 0 | 0 | 0 | 0 | - +-------------+-------------+-----------+--------------+------------+-------+---------+ - + ``raw_chars`` 列是 ``context`` 与 ``question`` 拼起来的结果(连接的地方加入了 ``[SEP]`` ), ``chars`` 是转为 + index 的值, ``target_start`` 为答案开始的位置, ``target_end`` 为答案结束的位置(闭区间); ``context_len`` + 指示的是 ``chars`` 列中 context 的长度。 + + :param max_len: """ def __init__(self, max_len=510): @@ -112,10 +100,10 @@ class CMRC2018BertPipe(Pipe): def process(self, data_bundle: DataBundle) -> DataBundle: r""" - 传入的DataSet应该具备以下的field + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该包含 ``raw_words`` : .. csv-table:: - :header:"title", "context", "question", "answers", "answer_starts", "id" + :header: "title", "context", "question", "answers", "answer_starts", "id" "范廷颂", "范廷颂枢机(,),圣名保禄·若瑟()...", "范廷颂是什么时候被任为主教的?", ["1963年"], ["30"], "TRAIN_186_QUERY_0" "范廷颂", "范廷颂枢机(,),圣名保禄·若瑟()...", "1990年,范廷颂担任什么职务?", ["1990年被擢升为天..."], ["41"],"TRAIN_186_QUERY_1" @@ -139,7 +127,7 @@ class CMRC2018BertPipe(Pipe): def process_from_file(self, paths=None) -> DataBundle: r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/summarization.py b/fastNLP/io/pipe/summarization.py index eb56a2c8..dc27651c 100644 --- a/fastNLP/io/pipe/summarization.py +++ b/fastNLP/io/pipe/summarization.py @@ -1,4 +1,3 @@ -r"""undocumented""" import os import numpy as np from functools import partial @@ -20,21 +19,23 @@ TAG_UNK = "X" class ExtCNNDMPipe(Pipe): r""" - 对CNN/Daily Mail数据进行适用于extractive summarization task的预处理,预处理之后的数据,具备以下结构: + 对 **CNN/Daily Mail** 数据进行适用于 ``extractive summarization task`` 的预处理,预处理之后的数据具备以下结构: .. csv-table:: :header: "text", "summary", "label", "publication", "text_wd", "words", "seq_len", "target" - + + "['I got new tires from them and... ','...']", "['The new tires...','...']", "[0, 1]", "cnndm", "[['I','got',...'.'],...,['...']]", "[[54,89,...,5],...,[9,43,..,0]]", "[1,1,...,0]", "[0,1,...,0]" + "['Don't waste your time. We had two...','...']", "['Time is precious','...']", "[1]", "cnndm", "[['Don't','waste',...,'.'],...,['...']]", "[[5234,653,...,5],...,[87,234,..,0]]", "[1,1,...,0]", "[1,1,...,0]" + "['...']", "['...']", "[]", "cnndm", "[[''],...,['']]", "[[],...,[]]", "[]", "[]" + + :param vocab_size: 词表大小 + :param sent_max_len: 句子最大长度,不足的句子将 padding ,超出的将截断 + :param doc_max_timesteps: 文章最多句子个数,不足的将 padding,超出的将截断 + :param vocab_path: 外部词表路径 + :param domain: 是否需要建立 domain 词表 + :param num_proc: 处理数据时使用的进程数目。 """ - def __init__(self, vocab_size, sent_max_len, doc_max_timesteps, vocab_path=None, domain=False, num_proc=0): - r""" - - :param vocab_size: int, 词表大小 - :param sent_max_len: int, 句子最大长度,不足的句子将padding,超出的将截断 - :param doc_max_timesteps: int, 文章最多句子个数,不足的将padding,超出的将截断 - :param vocab_path: str, 外部词表路径 - :param domain: bool, 是否需要建立domain词表 - """ + def __init__(self, vocab_size: int, sent_max_len: int, doc_max_timesteps: int, vocab_path=None, domain=False, num_proc=0): self.vocab_size = vocab_size self.vocab_path = vocab_path self.sent_max_len = sent_max_len @@ -44,23 +45,24 @@ class ExtCNNDMPipe(Pipe): def process(self, data_bundle: DataBundle): r""" - 传入的DataSet应该具备如下的结构 + ``data_bunlde`` 中的 :class:`~fastNLP.core.DataSet` 应该具备以下结构: .. csv-table:: :header: "text", "summary", "label", "publication" - ["I got new tires from them and... ","..."], ["The new tires...","..."], [0, 1], "cnndm" - ["Don't waste your time. We had two...","..."], ["Time is precious","..."], [1], "cnndm" - ["..."], ["..."], [], "cnndm" + "['I got new tires from them and... ','...']", "['The new tires...','...']", "[0, 1]", "cnndm" + "['Don't waste your time. We had two...','...']", "['Time is precious','...']", "[1]", "cnndm" + "['...']", ['...']", "[]", "cnndm" :param data_bundle: - :return: 处理后的 ``data_bundle`` + :return: 处理后的 ``data_bundle``,新增以下列: + .. csv-table:: :header: "text_wd", "words", "seq_len", "target" - [["I","got",..."."],...,["..."]], [[54,89,...,5],...,[9,43,..,0]], [1,1,...,0], [0,1,...,0] - [["Don't","waste",...,"."],...,["..."]], [[5234,653,...,5],...,[87,234,..,0]], [1,1,...,0], [1,1,...,0] - [[""],...,[""]], [[],...,[]], [], [] + "[['I','got',...'.'],...,['...']]", "[[54,89,...,5],...,[9,43,..,0]]", "[1,1,...,0]", "[0,1,...,0]" + "[['Don't','waste',...,'.'],...,['...']]", "[[5234,653,...,5],...,[87,234,..,0]]", "[1,1,...,0]", "[1,1,...,0]" + "[[''],...,['']]", "[[],...,[]]", "[]", "[]" """ if self.vocab_path is None: @@ -117,7 +119,7 @@ class ExtCNNDMPipe(Pipe): def process_from_file(self, paths=None): r""" - 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load()` + 传入文件路径,生成处理好的 :class:`~fastNLP.io.DataBundle` 对象。``paths`` 支持的路径形式可以参考 :meth:`fastNLP.io.Loader.load` :param paths: :return: diff --git a/fastNLP/io/pipe/utils.py b/fastNLP/io/pipe/utils.py index 50047d04..3f1b8563 100644 --- a/fastNLP/io/pipe/utils.py +++ b/fastNLP/io/pipe/utils.py @@ -1,5 +1,3 @@ -r"""undocumented""" - __all__ = [ "iob2", "iob2bioes", @@ -17,10 +15,10 @@ from pkg_resources import parse_version def iob2(tags: List[str]) -> List[str]: r""" - 检查数据是否是合法的IOB数据,如果是IOB1会被自动转换为IOB2。两种格式的区别见 + 检查数据是否是合法的 ``IOB`` 数据,如果是 ``IOB1`` 会被自动转换为 ``IOB2`` 。两种格式的区别见 https://datascience.stackexchange.com/questions/37824/difference-between-iob-and-iob2-format - :param tags: 需要转换的tags + :param tags: 需要转换的 tags """ for i, tag in enumerate(tags): if tag == "O": @@ -41,8 +39,9 @@ def iob2(tags: List[str]) -> List[str]: def iob2bioes(tags: List[str]) -> List[str]: r""" - 将iob的tag转换为bioes编码 - :param tags: + 将 ``iob`` 的 tag 转换为 ``bioes`` 编码 + + :param tags: 需要转换的 tags :return: """ new_tags = [] @@ -69,9 +68,10 @@ def iob2bioes(tags: List[str]) -> List[str]: def get_tokenizer(tokenize_method: str, lang='en'): r""" - :param str tokenize_method: 获取tokenzier方法 - :param str lang: 语言,当前仅支持en - :return: tokenize函数 + :param tokenize_method: 获取 tokenzier 方法,支持 ``['spacy', 'raw', 'cn-char']`` 。``'raw'`` 表示使用空格作为切分, ``'cn-char'`` 表示 + 按字符切分,``'spacy'`` 则使用 :mod:`spacy` 库进行分词。 + :param lang: :mod:`spacy` 使用的语言,当前仅支持 ``'en'`` 。 + :return: tokenize 函数 """ tokenizer_dict = { 'spacy': None, From 278fd24423c076414adc433ccdb7d1779bda0dc7 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 13:57:39 +0000 Subject: [PATCH 08/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=AF=E5=88=A0?= =?UTF-8?q?=E7=9A=84rst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/fastNLP.io.loader.conll.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/source/fastNLP.io.loader.conll.rst diff --git a/docs/source/fastNLP.io.loader.conll.rst b/docs/source/fastNLP.io.loader.conll.rst new file mode 100644 index 00000000..96123649 --- /dev/null +++ b/docs/source/fastNLP.io.loader.conll.rst @@ -0,0 +1,7 @@ +fastNLP.io.loader.conll module +============================== + +.. automodule:: fastNLP.io.loader.conll + :members: + :undoc-members: + :show-inheritance: From fffcdf79dbec42055fcf452139cec8dbecafc19e Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 13:58:51 +0000 Subject: [PATCH 09/14] small --- docs/source/fastNLP.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/fastNLP.rst b/docs/source/fastNLP.rst index 55776c22..f3e245fe 100644 --- a/docs/source/fastNLP.rst +++ b/docs/source/fastNLP.rst @@ -18,5 +18,4 @@ Subpackages fastNLP.io fastNLP.models fastNLP.modules - .. 以下为手动添加 fastNLP.transformers \ No newline at end of file From 011cc1bc2c546ead39d0399d680a6a42981f1fa2 Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 14:48:22 +0000 Subject: [PATCH 10/14] =?UTF-8?q?=E4=B8=BA=20cache=5Fresults=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastNLP/core/utils/cache_results.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fastNLP/core/utils/cache_results.py b/fastNLP/core/utils/cache_results.py index d462c06c..dc114b48 100644 --- a/fastNLP/core/utils/cache_results.py +++ b/fastNLP/core/utils/cache_results.py @@ -1,3 +1,14 @@ +""" +:func:`cache_results` 函数是 **fastNLP** 中用于缓存数据的装饰器,通过该函数您可以省去调试代码过程中一些耗时过长程序 +带来的时间开销。比如在加载并处理较大的数据时,每次修改训练参数都需要从头开始执行处理数据的过程,那么 :func:`cache_results` +便可以跳过这部分漫长的时间。详细的使用方法和原理请参见下面的说明。 + +.. warning:: + + 如果您发现对代码进行修改之后程序执行的结果没有变化,很有可能是这个函数的原因;届时删除掉缓存数据即可。 + +""" + from datetime import datetime import hashlib import _pickle From a862c31b71b0b7e6b9a3ce32eddfe48d5c58f7cc Mon Sep 17 00:00:00 2001 From: x54-729 <17307130121@fudan.edu.cn> Date: Thu, 7 Jul 2022 14:55:42 +0000 Subject: [PATCH 11/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20fastnlp=5Ftorch=5Ftu?= =?UTF-8?q?torial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tutorials/fastnlp_torch_tutorial.ipynb | 869 ++++++++++++++++++ 1 file changed, 869 insertions(+) create mode 100644 docs/source/tutorials/fastnlp_torch_tutorial.ipynb diff --git a/docs/source/tutorials/fastnlp_torch_tutorial.ipynb b/docs/source/tutorials/fastnlp_torch_tutorial.ipynb new file mode 100644 index 00000000..9633ac7f --- /dev/null +++ b/docs/source/tutorials/fastnlp_torch_tutorial.ipynb @@ -0,0 +1,869 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6011adf8", + "metadata": {}, + "source": [ + "# 10 分钟快速上手 fastNLP torch\n", + "\n", + "在这个例子中,我们将使用BERT来解决conll2003数据集中的命名实体识别任务。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e166c051", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--2022-07-07 10:12:29-- https://data.deepai.org/conll2003.zip\n", + "Resolving data.deepai.org (data.deepai.org)... 138.201.36.183\n", + "Connecting to data.deepai.org (data.deepai.org)|138.201.36.183|:443... connected.\n", + "WARNING: cannot verify data.deepai.org's certificate, issued by ‘CN=R3,O=Let's Encrypt,C=US’:\n", + " Issued certificate has expired.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 982975 (960K) [application/x-zip-compressed]\n", + "Saving to: ‘conll2003.zip’\n", + "\n", + "conll2003.zip 100%[===================>] 959.94K 653KB/s in 1.5s \n", + "\n", + "2022-07-07 10:12:32 (653 KB/s) - ‘conll2003.zip’ saved [982975/982975]\n", + "\n", + "Archive: conll2003.zip\n", + " inflating: conll2003/metadata \n", + " inflating: conll2003/test.txt \n", + " inflating: conll2003/train.txt \n", + " inflating: conll2003/valid.txt \n" + ] + } + ], + "source": [ + "# Linux/Mac 下载数据,并解压\n", + "import platform\n", + "if platform.system() != \"Windows\":\n", + " !wget https://data.deepai.org/conll2003.zip --no-check-certificate -O conll2003.zip\n", + " !unzip conll2003.zip -d conll2003\n", + "# Windows用户请通过复制该url到浏览器下载该数据并解压" + ] + }, + { + "cell_type": "markdown", + "id": "f7acbf1f", + "metadata": {}, + "source": [ + "## 目录\n", + "接下来我们将按照以下的内容介绍在如何通过fastNLP减少工程性代码的撰写 \n", + "- 1. 数据加载\n", + "- 2. 数据预处理、数据缓存\n", + "- 3. DataLoader\n", + "- 4. 模型准备\n", + "- 5. Trainer的使用\n", + "- 6. Evaluator的使用\n", + "- 7. 其它【待补充】\n", + " - 7.1 使用多卡进行训练、评测\n", + " - 7.2 使用ZeRO优化\n", + " - 7.3 通过overfit测试快速验证模型\n", + " - 7.4 复杂Monitor的使用\n", + " - 7.5 训练过程中,使用不同的测试函数\n", + " - 7.6 更有效率的Sampler\n", + " - 7.7 保存模型\n", + " - 7.8 断点重训\n", + " - 7.9 使用huggingface datasets\n", + " - 7.10 使用torchmetrics来作为metric\n", + " - 7.11 将预测结果写出到文件\n", + " - 7.12 混合 dataset 训练\n", + " - 7.13 logger的使用\n", + " - 7.14 自定义分布式 Metric 。\n", + " - 7.15 通过batch_step_fn实现R-Drop" + ] + }, + { + "cell_type": "markdown", + "id": "0657dfba", + "metadata": {}, + "source": [ + "#### 1. 数据加载\n", + "目前在``conll2003``目录下有``train.txt``, ``test.txt``与``valid.txt``三个文件,文件的格式为[conll格式](https://universaldependencies.org/format.html),其编码格式为 [BIO](https://blog.csdn.net/HappyRocking/article/details/79716212) 类型。可以通过继承 fastNLP.io.Loader 来简化加载过程,继承了 Loader 函数后,只需要在实现读取单个文件 _load() 函数即可。" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c557f0ba", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('../..')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6f59e438", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

    \n",
    +       "
    \n" + ], + "text/plain": [ + "\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In total 3 datasets:\n", + "\ttrain has 14987 instances.\n", + "\ttest has 3684 instances.\n", + "\tdev has 3466 instances.\n", + "\n" + ] + } + ], + "source": [ + "from fastNLP import DataSet, Instance\n", + "from fastNLP.io import Loader\n", + "\n", + "\n", + "# 继承Loader之后,我们只需要实现其中_load()方法,_load()方法传入一个文件路径,返回一个fastNLP DataSet对象,其目的是读取一个文件。\n", + "class ConllLoader(Loader):\n", + " def _load(self, path):\n", + " ds = DataSet()\n", + " with open(path, 'r') as f:\n", + " segments = []\n", + " for line in f:\n", + " line = line.strip()\n", + " if line == '': # 如果为空行,说明需要切换到下一句了。\n", + " if segments:\n", + " raw_words = [s[0] for s in segments]\n", + " raw_target = [s[1] for s in segments]\n", + " # 将一个 sample 插入到 DataSet中\n", + " ds.append(Instance(raw_words=raw_words, raw_target=raw_target)) \n", + " segments = []\n", + " else:\n", + " parts = line.split()\n", + " assert len(parts)==4\n", + " segments.append([parts[0], parts[-1]])\n", + " return ds\n", + " \n", + "\n", + "# 直接使用 load() 方法加载数据集, 返回的 data_bundle 是一个 fastNLP.io.DataBundle 对象,该对象相当于将多个 dataset 放置在一起,\n", + "# 可以方便之后的预处理,DataBundle 支持的接口可以在 !!! 查看。\n", + "data_bundle = ConllLoader().load({\n", + " 'train': 'conll2003/train.txt',\n", + " 'test': 'conll2003/test.txt',\n", + " 'dev': 'conll2003/valid.txt'\n", + "})\n", + "\"\"\"\n", + "也可以通过 ConllLoader().load('conll2003/') 来读取,其原理是load()函数将尝试从'conll2003/'文件夹下寻找文件名称中包含了\n", + "'train'、'test'和'dev'的文件,并分别读取将其命名为'train'、'test'和'dev'(如文件夹中同一个关键字出现在了多个文件名中将导致报错,\n", + "此时请通过dict的方式传入路径信息)。但在我们这里的数据里,没有文件包含dev,所以无法直接使用文件夹读取,转而通过dict的方式传入读取的路径,\n", + "该dict的key也将作为读取的数据集的名称,value即对应的文件路径。\n", + "\"\"\"\n", + "\n", + "print(data_bundle) # 打印 data_bundle 可以查看包含的 DataSet \n", + "# data_bundle.get_dataset('train') # 可以获取单个 dataset" + ] + }, + { + "cell_type": "markdown", + "id": "57ae314d", + "metadata": {}, + "source": [ + "#### 2. 数据预处理\n", + "接下来,我们将演示如何通过fastNLP提供的apply函数方便快捷地进行预处理。我们需要进行的预处理操作有: \n", + "(1)使用BertTokenizer将文本转换为index;同时记录每个word被bpe之后第一个bpe的index,用于得到word的hidden state; \n", + "(2)使用[Vocabulary](../fastNLP)来将raw_target转换为序号。 " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "96389988", + "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": {
    +      "application/vnd.jupyter.widget-view+json": {
    +       "model_id": "c3bd41a323c94a41b409d29a5d4079b6",
    +       "version_major": 2,
    +       "version_minor": 0
    +      },
    +      "text/plain": [
    +       "Output()"
    +      ]
    +     },
    +     "metadata": {},
    +     "output_type": "display_data"
    +    },
    +    {
    +     "name": "stderr",
    +     "output_type": "stream",
    +     "text": [
    +      "IOPub message rate exceeded.\n",
    +      "The notebook server will temporarily stop sending output\n",
    +      "to the client in order to avoid crashing it.\n",
    +      "To change this limit, set the config variable\n",
    +      "`--NotebookApp.iopub_msg_rate_limit`.\n",
    +      "\n",
    +      "Current values:\n",
    +      "NotebookApp.iopub_msg_rate_limit=1000.0 (msgs/sec)\n",
    +      "NotebookApp.rate_limit_window=3.0 (secs)\n",
    +      "\n"
    +     ]
    +    },
    +    {
    +     "data": {
    +      "text/html": [
    +       "
    \n"
    +      ],
    +      "text/plain": []
    +     },
    +     "metadata": {},
    +     "output_type": "display_data"
    +    },
    +    {
    +     "data": {
    +      "text/html": [
    +       "
    [10:48:13] INFO     Save cache to /remote-home/hyan01/exps/fastNLP/fastN cache_results.py:332\n",
    +       "                    LP/demo/torch_tutorial/caches/c7f74559_cache.pkl.                        \n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m[10:48:13]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Save cache to \u001b[35m/remote-home/hyan01/exps/fastNLP/fastN\u001b[0m \u001b]8;id=831330;file://../../fastNLP/core/utils/cache_results.py\u001b\\\u001b[2mcache_results.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=609545;file://../../fastNLP/core/utils/cache_results.py#332\u001b\\\u001b[2m332\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m \u001b[35mLP/demo/torch_tutorial/caches/\u001b[0m\u001b[95mc7f74559_cache.pkl.\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# fastNLP 中提供了BERT, RoBERTa, GPT, BART 模型,更多的预训练模型请直接使用transformers\n", + "from fastNLP.transformers.torch import BertTokenizer\n", + "from fastNLP import cache_results, Vocabulary\n", + "\n", + "# 使用cache_results来装饰函数,会将函数的返回结果缓存到'caches/{param_hash_id}_cache.pkl'路径中(其中{param_hash_id}是根据\n", + "# 传递给 process_data 函数参数决定的,因此当函数的参数变化时,会再生成新的缓存文件。如果需要重新生成新的缓存,(a) 可以在调用process_data\n", + "# 函数时,额外传入一个_refresh=True的参数; 或者(b)删除相应的缓存文件。此外,保存结果时,cache_results默认还会\n", + "# 记录 process_data 函数源码的hash值,当其源码发生了变动,直接读取缓存会发出警告,以防止在修改预处理代码之后,忘记刷新缓存。)\n", + "@cache_results('caches/cache.pkl')\n", + "def process_data(data_bundle, model_name):\n", + " tokenizer = BertTokenizer.from_pretrained(model_name)\n", + " def bpe(raw_words):\n", + " bpes = [tokenizer.cls_token_id]\n", + " first = [0]\n", + " first_index = 1 # 记录第一个bpe的位置\n", + " for word in raw_words:\n", + " bpe = tokenizer.encode(word, add_special_tokens=False)\n", + " bpes.extend(bpe)\n", + " first.append(first_index)\n", + " first_index += len(bpe)\n", + " bpes.append(tokenizer.sep_token_id)\n", + " first.append(first_index)\n", + " return {'input_ids': bpes, 'input_len': len(bpes), 'first': first, 'first_len': len(raw_words)}\n", + " # 对data_bundle中每个dataset的每一条数据中的raw_words使用bpe函数,并且将返回的结果加入到每条数据中。\n", + " data_bundle.apply_field_more(bpe, field_name='raw_words', num_proc=4)\n", + " # 对应我们还有 apply_field() 函数,该函数和 apply_field_more() 的区别在于传入到 apply_field() 中的函数应该返回一个 field 的\n", + " # 内容(即不需要用dict包裹了)。此外,我们还提供了 data_bundle.apply() ,传入 apply() 的函数需要支持传入一个Instance对象,\n", + " # 更多信息可以参考对应的文档。\n", + " \n", + " # tag的词表,由于这是词表,所以不需要有padding和unk\n", + " tag_vocab = Vocabulary(padding=None, unknown=None)\n", + " # 从 train 数据的 raw_target 中获取建立词表\n", + " tag_vocab.from_dataset(data_bundle.get_dataset('train'), field_name='raw_target')\n", + " # 使用词表将每个 dataset 中的raw_target转为数字,并且将写入到target这个field中\n", + " tag_vocab.index_dataset(data_bundle.datasets.values(), field_name='raw_target', new_field_name='target')\n", + " \n", + " # 可以将 vocabulary 绑定到 data_bundle 上,方便之后使用。\n", + " data_bundle.set_vocab(tag_vocab, field_name='target')\n", + " \n", + " return data_bundle, tokenizer\n", + "\n", + "data_bundle, tokenizer = process_data(data_bundle, 'bert-base-cased', _refresh=True) # 第一次调用耗时较长,第二次调用则会直接读取缓存的文件\n", + "# data_bundle = process_data(data_bundle, 'bert-base-uncased') # 由于参数变化,fastNLP 会再次生成新的缓存文件。 " + ] + }, + { + "cell_type": "markdown", + "id": "80036fcd", + "metadata": {}, + "source": [ + "### 3. DataLoader \n", + "由于现在的深度学习算法大都基于 mini-batch 进行优化,因此需要将多个 sample 组合成一个 batch 再输入到模型之中。在自然语言处理中,不同的 sample 往往长度不一致,需要进行 padding 操作。在fastNLP中,我们使用 fastNLP.TorchDataLoader 帮助用户快速进行 padding ,我们使用了 !!!fastNLP.Collator!!! 对象来进行 pad ,Collator 会在迭代过程中根据第一个 batch 的数据自动判定每个 field 是否可以进行 pad ,可以通过 Collator.set_pad() 函数修改某个 field 的 pad 行为。" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "09494695", + "metadata": {}, + "outputs": [], + "source": [ + "from fastNLP import prepare_dataloader\n", + "\n", + "# 将 data_bundle 中每个 dataset 取出并构造出相应的 DataLoader 对象。返回的 dls 是一个 dict ,包含了 'train', 'test', 'dev' 三个\n", + "# fastNLP.TorchDataLoader 对象。\n", + "dls = prepare_dataloader(data_bundle, batch_size=24) \n", + "\n", + "\n", + "# fastNLP 将默认尝试对所有 field 都进行 pad ,如果当前 field 是不可 pad 的类型,则不进行pad;如果是可以 pad 的类型\n", + "# 默认使用 0 进行 pad 。\n", + "for dl in dls.values():\n", + " # 可以通过 set_pad 修改 padding 的行为。\n", + " dl.set_pad('input_ids', pad_val=tokenizer.pad_token_id)\n", + " # 如果希望忽略某个 field ,可以通过 set_ignore 方法。\n", + " dl.set_ignore('raw_target')\n", + " dl.set_pad('target', pad_val=-100)\n", + "# 另一种设置的方法是,可以在 dls = prepare_dataloader(data_bundle, batch_size=32) 之前直接调用 \n", + "# data_bundle.set_pad('input_ids', pad_val=tokenizer.pad_token_id); data_bundle.set_ignore('raw_target')来进行设置。\n", + "# DataSet 也支持这两个方法。\n", + "# 若此时调用 batch = next(dls['train']),则 batch 是一个 dict ,其中包含了\n", + "# 'input_ids': torch.LongTensor([batch_size, max_len])\n", + "# 'input_len': torch.LongTensor([batch_size])\n", + "# 'first': torch.LongTensor([batch_size, max_len'])\n", + "# 'first_len': torch.LongTensor([batch_size])\n", + "# 'target': torch.LongTensor([batch_size, max_len'-2])\n", + "# 'raw_words': List[List[str]] # 因为无法判断,所以 Collator 不会做任何处理" + ] + }, + { + "cell_type": "markdown", + "id": "3583df6d", + "metadata": {}, + "source": [ + "### 4. 模型准备\n", + "传入给fastNLP的模型,需要有两个特殊的方法``train_step``、``evaluate_step``,前者默认在 fastNLP.Trainer 中进行调用,后者默认在 fastNLP.Evaluator 中调用。如果模型中没有``train_step``方法,则Trainer会直接使用模型的``forward``函数;如果模型没有``evaluate_step``方法,则Evaluator会直接使用模型的``forward``函数。``train_step``方法(或当其不存在时,``forward``方法)的返回值必须为 dict 类型,并且必须包含``loss``这个 key 。\n", + "\n", + "此外fastNLP会使用形参名匹配的方式进行参数传递,例如以下模型\n", + "```python\n", + "class Model(nn.Module):\n", + " def train_step(self, x, y):\n", + " return {'loss': (x-y).abs().mean()}\n", + "```\n", + "fastNLP将尝试从 DataLoader 返回的 batch(假设包含的 key 为 input_ids, target) 中寻找 'x' 和 'y' 这两个 key ,如果没有找到则会报错。有以下的方法可以解决报错\n", + "- 修改 train_step 的参数为(input_ids, target),以保证和 DataLoader 返回的 batch 中的 key 匹配\n", + "- 修改 DataLoader 中返回 batch 的 key 的名字为 (x, y)\n", + "- 在 Trainer 中传入参数 train_input_mapping={'input_ids': 'x', 'target': 'y'} 将输入进行映射,train_input_mapping 也可以是一个函数,更多 train_input_mapping 的介绍可以参考文档。\n", + "\n", + "``evaluate_step``也是使用同样的匹配方式,前两条解决方法是一致的,第三种解决方案中,需要在 Evaluator 中传入 evaluate_input_mapping={'input_ids': 'x', 'target': 'y'}。" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "f131c1a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    [10:48:21] WARNING  Some weights of the model checkpoint at            modeling_utils.py:1490\n",
    +       "                    bert-base-uncased were not used when initializing                        \n",
    +       "                    BertModel: ['cls.predictions.bias',                                      \n",
    +       "                    'cls.predictions.transform.LayerNorm.weight',                            \n",
    +       "                    'cls.seq_relationship.weight',                                           \n",
    +       "                    'cls.predictions.decoder.weight',                                        \n",
    +       "                    'cls.predictions.transform.dense.weight',                                \n",
    +       "                    'cls.predictions.transform.LayerNorm.bias',                              \n",
    +       "                    'cls.predictions.transform.dense.bias',                                  \n",
    +       "                    'cls.seq_relationship.bias']                                             \n",
    +       "                    - This IS expected if you are initializing                               \n",
    +       "                    BertModel from the checkpoint of a model trained                         \n",
    +       "                    on another task or with another architecture (e.g.                       \n",
    +       "                    initializing a BertForSequenceClassification model                       \n",
    +       "                    from a BertForPreTraining model).                                        \n",
    +       "                    - This IS NOT expected if you are initializing                           \n",
    +       "                    BertModel from the checkpoint of a model that you                        \n",
    +       "                    expect to be exactly identical (initializing a                           \n",
    +       "                    BertForSequenceClassification model from a                               \n",
    +       "                    BertForSequenceClassification model).                                    \n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m[10:48:21]\u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m Some weights of the model checkpoint at \u001b]8;id=387614;file://../../fastNLP/transformers/torch/modeling_utils.py\u001b\\\u001b[2mmodeling_utils.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=648168;file://../../fastNLP/transformers/torch/modeling_utils.py#1490\u001b\\\u001b[2m1490\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m bert-base-uncased were not used when initializing \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertModel: \u001b[1m[\u001b[0m\u001b[32m'cls.predictions.bias'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.predictions.transform.LayerNorm.weight'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.seq_relationship.weight'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.predictions.decoder.weight'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.predictions.transform.dense.weight'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.predictions.transform.LayerNorm.bias'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.predictions.transform.dense.bias'\u001b[0m, \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[32m'cls.seq_relationship.bias'\u001b[0m\u001b[1m]\u001b[0m \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m - This IS expected if you are initializing \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertModel from the checkpoint of a model trained \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m on another task or with another architecture \u001b[1m(\u001b[0me.g. \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m initializing a BertForSequenceClassification model \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m from a BertForPreTraining model\u001b[1m)\u001b[0m. \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m - This IS NOT expected if you are initializing \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertModel from the checkpoint of a model that you \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m expect to be exactly identical \u001b[1m(\u001b[0minitializing a \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertForSequenceClassification model from a \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertForSequenceClassification model\u001b[1m)\u001b[0m. \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
               INFO     All the weights of BertModel were initialized from modeling_utils.py:1507\n",
    +       "                    the model checkpoint at bert-base-uncased.                               \n",
    +       "                    If your task is similar to the task the model of                         \n",
    +       "                    the checkpoint was trained on, you can already use                       \n",
    +       "                    BertModel for predictions without further                                \n",
    +       "                    training.                                                                \n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m All the weights of BertModel were initialized from \u001b]8;id=544687;file://../../fastNLP/transformers/torch/modeling_utils.py\u001b\\\u001b[2mmodeling_utils.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=934505;file://../../fastNLP/transformers/torch/modeling_utils.py#1507\u001b\\\u001b[2m1507\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m the model checkpoint at bert-base-uncased. \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m If your task is similar to the task the model of \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m the checkpoint was trained on, you can already use \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m BertModel for predictions without further \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m training. \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import torch\n", + "from torch import nn\n", + "from torch.nn.utils.rnn import pad_sequence\n", + "from fastNLP.transformers.torch import BertModel\n", + "from fastNLP import seq_len_to_mask\n", + "import torch.nn.functional as F\n", + "\n", + "\n", + "class BertNER(nn.Module):\n", + " def __init__(self, model_name, num_class, tag_vocab=None):\n", + " super().__init__()\n", + " self.bert = BertModel.from_pretrained(model_name)\n", + " self.mlp = nn.Sequential(nn.Linear(self.bert.config.hidden_size, self.bert.config.hidden_size),\n", + " nn.Dropout(0.3),\n", + " nn.Linear(self.bert.config.hidden_size, num_class))\n", + " self.tag_vocab = tag_vocab # 这里传入 tag_vocab 的目的是为了演示 constrined_decode \n", + " if tag_vocab is not None:\n", + " self._init_constrained_transition()\n", + " \n", + " def forward(self, input_ids, input_len, first):\n", + " attention_mask = seq_len_to_mask(input_len)\n", + " outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)\n", + " last_hidden_state = outputs.last_hidden_state\n", + " first = first.unsqueeze(-1).repeat(1, 1, last_hidden_state.size(-1))\n", + " first_bpe_state = last_hidden_state.gather(dim=1, index=first)\n", + " first_bpe_state = first_bpe_state[:, 1:-1] # 删除 cls 和 sep\n", + " \n", + " pred = self.mlp(first_bpe_state)\n", + " return {'pred': pred}\n", + " \n", + " def train_step(self, input_ids, input_len, first, target):\n", + " pred = self(input_ids, input_len, first)['pred']\n", + " loss = F.cross_entropy(pred.transpose(1, 2), target)\n", + " return {'loss': loss}\n", + " \n", + " def evaluate_step(self, input_ids, input_len, first):\n", + " pred = self(input_ids, input_len, first)['pred'].argmax(dim=-1)\n", + " return {'pred': pred}\n", + " \n", + " def constrained_decode(self, input_ids, input_len, first, first_len):\n", + " # 这个函数在推理时,将保证解码出来的 tag 一定不与前一个 tag 矛盾【例如一定不会出现 B-person 后面接着 I-Location 的情况】\n", + " # 本身这个需求可以在 Metric 中实现,这里在模型中实现的目的是为了方便演示:如何在fastNLP中使用不同的评测函数\n", + " pred = self(input_ids, input_len, first)['pred']\n", + " cons_pred = []\n", + " for _pred, _len in zip(pred, first_len):\n", + " _pred = _pred[:_len]\n", + " tags = [_pred[0].argmax(dim=-1).item()] # 这里就不考虑第一个位置非法的情况了\n", + " for i in range(1, _len):\n", + " tags.append((_pred[i] + self.transition[tags[-1]]).argmax().item())\n", + " cons_pred.append(torch.LongTensor(tags))\n", + " cons_pred = pad_sequence(cons_pred, batch_first=True)\n", + " return {'pred': cons_pred}\n", + " \n", + " def _init_constrained_transition(self):\n", + " from fastNLP.modules.torch import allowed_transitions\n", + " allowed_trans = allowed_transitions(self.tag_vocab)\n", + " transition = torch.ones((len(self.tag_vocab), len(self.tag_vocab)))*-100000.0\n", + " for s, e in allowed_trans:\n", + " transition[s, e] = 0\n", + " self.register_buffer('transition', transition)\n", + "\n", + "model = BertNER('bert-base-uncased', len(data_bundle.get_vocab('target')), data_bundle.get_vocab('target'))" + ] + }, + { + "cell_type": "markdown", + "id": "5aeee1e9", + "metadata": {}, + "source": [ + "### Trainer 的使用\n", + "fastNLP 的 Trainer 是用于对模型进行训练的部件。" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f4250f0b", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
    [10:49:22] INFO     Running evaluator sanity check for 2 batches.              trainer.py:661\n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m[10:49:22]\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=246773;file://../../fastNLP/core/controllers/trainer.py\u001b\\\u001b[2mtrainer.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=639347;file://../../fastNLP/core/controllers/trainer.py#661\u001b\\\u001b[2m661\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": [ + "\u001b[38;5;41m+++++++++++++++++++++++++++++ \u001b[0m\u001b[1mEval. results on Epoch:\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1m, Batch:\u001b[0m\u001b[1;36m0\u001b[0m\u001b[38;5;41m +++++++++++++++++++++++++++++\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
    {\n",
    +       "  \"f#f\": 0.402447,\n",
    +       "  \"pre#f\": 0.447906,\n",
    +       "  \"rec#f\": 0.365365\n",
    +       "}\n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\n", + " \u001b[1;34m\"f#f\"\u001b[0m: \u001b[1;36m0.402447\u001b[0m,\n", + " \u001b[1;34m\"pre#f\"\u001b[0m: \u001b[1;36m0.447906\u001b[0m,\n", + " \u001b[1;34m\"rec#f\"\u001b[0m: \u001b[1;36m0.365365\u001b[0m\n", + "\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
    [10:51:15] INFO     The best performance for monitor f#f:0.402447 was progress_callback.py:37\n",
    +       "                    achieved in Epoch:1, Global Batch:625. The                               \n",
    +       "                    evaluation result:                                                       \n",
    +       "                    {'f#f': 0.402447, 'pre#f': 0.447906, 'rec#f':                            \n",
    +       "                    0.365365}                                                                \n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m[10:51:15]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m The best performance for monitor f#\u001b[1;92mf:0\u001b[0m.\u001b[1;36m402447\u001b[0m was \u001b]8;id=192029;file://../../fastNLP/core/callbacks/progress_callback.py\u001b\\\u001b[2mprogress_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=994998;file://../../fastNLP/core/callbacks/progress_callback.py#37\u001b\\\u001b[2m37\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m achieved in Epoch:\u001b[1;36m1\u001b[0m, Global Batch:\u001b[1;36m625\u001b[0m. The \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m evaluation result: \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1m{\u001b[0m\u001b[32m'f#f'\u001b[0m: \u001b[1;36m0.402447\u001b[0m, \u001b[32m'pre#f'\u001b[0m: \u001b[1;36m0.447906\u001b[0m, \u001b[32m'rec#f'\u001b[0m: \u001b[2m \u001b[0m\n", + "\u001b[2;36m \u001b[0m \u001b[1;36m0.365365\u001b[0m\u001b[1m}\u001b[0m \u001b[2m \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" + }, + { + "data": { + "text/html": [ + "
               INFO     Loading best model from buffer with f#f:  load_best_model_callback.py:115\n",
    +       "                    0.402447...                                                              \n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Loading best model from buffer with f#f: \u001b]8;id=654516;file://../../fastNLP/core/callbacks/load_best_model_callback.py\u001b\\\u001b[2mload_best_model_callback.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=96586;file://../../fastNLP/core/callbacks/load_best_model_callback.py#115\u001b\\\u001b[2m115\u001b[0m\u001b]8;;\u001b\\\n", + "\u001b[2;36m \u001b[0m \u001b[1;36m0.402447\u001b[0m\u001b[33m...\u001b[0m \u001b[2m \u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from torch import optim\n", + "from fastNLP import Trainer, LoadBestModelCallback, TorchWarmupCallback\n", + "from fastNLP import SpanFPreRecMetric\n", + "\n", + "optimizer = optim.AdamW(model.parameters(), lr=2e-5)\n", + "callbacks = [\n", + " LoadBestModelCallback(), # 用于在训练结束之后加载性能最好的model的权重\n", + " TorchWarmupCallback()\n", + "] \n", + "\n", + "trainer = Trainer(model=model, train_dataloader=dls['train'], optimizers=optimizer, \n", + " evaluate_dataloaders=dls['dev'], \n", + " metrics={'f': SpanFPreRecMetric(tag_vocab=data_bundle.get_vocab('target'))}, \n", + " n_epochs=1, callbacks=callbacks, \n", + " # 在评测时将 dataloader 中的 first_len 映射 seq_len, 因为 Accuracy.update 接口需要输入一个名为 seq_len 的参数\n", + " evaluate_input_mapping={'first_len': 'seq_len'}, overfit_batches=0,\n", + " device=0, monitor='f#f', fp16=False) # fp16 为 True 的话,将使用 float16 进行训练。\n", + "trainer.run()" + ] + }, + { + "cell_type": "markdown", + "id": "c600a450", + "metadata": {}, + "source": [ + "### Evaluator的使用\n", + "fastNLP中用于评测数据的对象。" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "1b19f0ba", + "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/html": [
    +       "
    {'f#f': 0.390326, 'pre#f': 0.414741, 'rec#f': 0.368626}\n",
    +       "
    \n" + ], + "text/plain": [ + "\u001b[1m{\u001b[0m\u001b[32m'f#f'\u001b[0m: \u001b[1;36m0.390326\u001b[0m, \u001b[32m'pre#f'\u001b[0m: \u001b[1;36m0.414741\u001b[0m, \u001b[32m'rec#f'\u001b[0m: \u001b[1;36m0.368626\u001b[0m\u001b[1m}\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "{'f#f': 0.390326, 'pre#f': 0.414741, 'rec#f': 0.368626}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from fastNLP import Evaluator\n", + "from fastNLP import SpanFPreRecMetric\n", + "\n", + "evaluator = Evaluator(model=model, dataloaders=dls['test'], \n", + " metrics={'f': SpanFPreRecMetric(tag_vocab=data_bundle.get_vocab('target'))}, \n", + " evaluate_input_mapping={'first_len': 'seq_len'}, \n", + " device=0)\n", + "evaluator.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52f87770", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f723fe399df34917875ad74c2542508c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# 如果想评测一下使用 constrained decoding的性能,则可以通过传入 evaluate_fn 指定使用的函数\n", + "def input_mapping(x):\n", + " x['seq_len'] = x['first_len']\n", + " return x\n", + "evaluator = Evaluator(model=model, dataloaders=dls['test'], device=0,\n", + " metrics={'f': SpanFPreRecMetric(tag_vocab=data_bundle.get_vocab('target'))},\n", + " evaluate_fn='constrained_decode',\n", + " # 如果将 first_len 重新命名为了 seq_len, 将导致 constrained_decode 的输入缺少 first_len 参数,因此\n", + " # 额外重复一下 'first_len': 'first_len',使得这个参数不会消失。\n", + " evaluate_input_mapping=input_mapping)\n", + "evaluator.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "419e718b", + "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 +} From e1fbc2cfebb14f21ec3d675408d01a59522d3dc8 Mon Sep 17 00:00:00 2001 From: yhcc Date: Sun, 3 Jul 2022 14:09:41 +0800 Subject: [PATCH 12/14] =?UTF-8?q?progres=5Fbar=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastNLP/core/__init__.py | 1 + fastNLP/core/callbacks/__init__.py | 3 ++- fastNLP/core/callbacks/progress_callback.py | 3 ++- fastNLP/core/controllers/trainer.py | 10 ++++++---- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/fastNLP/core/__init__.py b/fastNLP/core/__init__.py index 300a342f..28479b05 100644 --- a/fastNLP/core/__init__.py +++ b/fastNLP/core/__init__.py @@ -7,6 +7,7 @@ __all__ = [ 'ProgressCallback', 'RichCallback', 'TqdmCallback', + 'RawTextCallback', "LRSchedCallback", 'LoadBestModelCallback', "EarlyStopCallback", diff --git a/fastNLP/core/callbacks/__init__.py b/fastNLP/core/callbacks/__init__.py index d1f19b96..feff9f9b 100644 --- a/fastNLP/core/callbacks/__init__.py +++ b/fastNLP/core/callbacks/__init__.py @@ -8,6 +8,7 @@ __all__ = [ 'ProgressCallback', 'RichCallback', 'TqdmCallback', + 'RawTextCallback', "LRSchedCallback", 'LoadBestModelCallback', @@ -31,7 +32,7 @@ from .callback import Callback from .callback_event import Event, Filter from .callback_manager import CallbackManager from .checkpoint_callback import CheckpointCallback -from .progress_callback import choose_progress_callback, ProgressCallback, RichCallback, TqdmCallback +from .progress_callback import choose_progress_callback, ProgressCallback, RichCallback, TqdmCallback, RawTextCallback from .lr_scheduler_callback import LRSchedCallback from .load_best_model_callback import LoadBestModelCallback from .early_stop_callback import EarlyStopCallback diff --git a/fastNLP/core/callbacks/progress_callback.py b/fastNLP/core/callbacks/progress_callback.py index 681ea4d3..eda0f564 100644 --- a/fastNLP/core/callbacks/progress_callback.py +++ b/fastNLP/core/callbacks/progress_callback.py @@ -5,7 +5,8 @@ __all__ = [ 'choose_progress_callback', 'ProgressCallback', 'RichCallback', - 'TqdmCallback' + 'TqdmCallback', + 'RawTextCallback' ] diff --git a/fastNLP/core/controllers/trainer.py b/fastNLP/core/controllers/trainer.py index ac934bd7..8a0b25ac 100644 --- a/fastNLP/core/controllers/trainer.py +++ b/fastNLP/core/controllers/trainer.py @@ -36,6 +36,7 @@ from fastNLP.core.log import logger from fastNLP.envs import FASTNLP_MODEL_FILENAME, FASTNLP_CHECKPOINT_FILENAME from fastNLP.core.utils.exceptions import EarlyStopException from fastNLP.core.dataloaders import OverfitDataLoader +from fastNLP.core.callbacks.progress_callback import ProgressCallback class Trainer(TrainerEventTrigger): @@ -554,15 +555,16 @@ class Trainer(TrainerEventTrigger): evaluate_dataloaders = self.dataloader if evaluate_dataloaders is not None: check_evaluate_every(evaluate_every) - progress_bar = kwargs.get('progress_bar', 'auto') # 如果不为 - if not (isinstance(progress_bar, str) or progress_bar is None): # 应该是ProgressCallback,获取其名称。 - progress_bar = progress_bar.name + progress_bar_name = None + for callback in self.callback_manager.class_callbacks: + if isinstance(callback, ProgressCallback): + progress_bar_name = callback.name self.evaluator = Evaluator(model=model, dataloaders=evaluate_dataloaders, metrics=metrics, driver=self.driver, evaluate_batch_step_fn=evaluate_batch_step_fn, evaluate_fn=evaluate_fn, input_mapping=evaluate_input_mapping, output_mapping=evaluate_output_mapping, fp16=fp16, verbose=0, use_dist_sampler=kwargs.get("evaluate_use_dist_sampler", use_dist_sampler), - progress_bar=progress_bar, + progress_bar=progress_bar_name, check_dataloader_legality=kwargs.get('check_dataloader_legality', True)) else: raise ValueError("You have set 'evaluate_dataloaders' but forget to set 'metrics'.") From 3ea094298000c6148dfd5bcc52d65e88e85fe582 Mon Sep 17 00:00:00 2001 From: yhcc Date: Wed, 6 Jul 2022 22:34:27 +0800 Subject: [PATCH 13/14] export more function --- fastNLP/core/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fastNLP/core/__init__.py b/fastNLP/core/__init__.py index 28479b05..10472917 100644 --- a/fastNLP/core/__init__.py +++ b/fastNLP/core/__init__.py @@ -69,6 +69,12 @@ __all__ = [ "JittorMPIDriver", "OneflowSingleDriver", "OneflowDDPDriver", + "torch_seed_everything", + "paddle_seed_everything", + "oneflow_seed_everything", + "torch_move_data_to_device", + 'paddle_move_data_to_device', + 'oneflow_move_data_to_device', # log "logger", From c3dbeca51abdf3c49ad49a48d390111945e89b08 Mon Sep 17 00:00:00 2001 From: yhcc Date: Thu, 7 Jul 2022 23:28:30 +0800 Subject: [PATCH 14/14] merge --- README.md | 267 ++++++++++++------ .../core/callbacks/more_evaluate_callback.py | 4 - .../torch_lr_sched_callback.py | 2 +- fastNLP/core/controllers/evaluator.py | 13 +- fastNLP/core/controllers/trainer.py | 2 +- .../dataloaders/oneflow_dataloader/fdl.py | 4 + .../core/dataloaders/paddle_dataloader/fdl.py | 2 + .../core/dataloaders/torch_dataloader/fdl.py | 4 + fastNLP/core/metrics/accuracy.py | 3 +- .../core/metrics/span_f1_pre_rec_metric.py | 2 +- fastNLP/core/vocabulary.py | 36 ++- fastNLP/io/data_bundle.py | 14 +- fastNLP/io/utils.py | 8 +- setup.py | 4 +- 14 files changed, 243 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 74090646..9c03fe30 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,208 @@ # fastNLP -[![Build Status](https://travis-ci.org/fastnlp/fastNLP.svg?branch=master)](https://travis-ci.org/fastnlp/fastNLP) -[![codecov](https://codecov.io/gh/fastnlp/fastNLP/branch/master/graph/badge.svg)](https://codecov.io/gh/fastnlp/fastNLP) -[![Pypi](https://img.shields.io/pypi/v/fastNLP.svg)](https://pypi.org/project/fastNLP) -![Hex.pm](https://img.shields.io/hexpm/l/plug.svg) -[![Documentation Status](https://readthedocs.org/projects/fastnlp/badge/?version=latest)](http://fastnlp.readthedocs.io/?badge=latest) -fastNLP是一款轻量级的自然语言处理(NLP)工具包,目标是快速实现NLP任务以及构建复杂模型。 +[//]: # ([![Build Status](https://travis-ci.org/fastnlp/fastNLP.svg?branch=master)](https://travis-ci.org/fastnlp/fastNLP)) -fastNLP具有如下的特性: - -- 统一的Tabular式数据容器,简化数据预处理过程; -- 内置多种数据集的Loader和Pipe,省去预处理代码; -- 各种方便的NLP工具,例如Embedding加载(包括ELMo和BERT)、中间数据cache等; -- 部分[数据集与预训练模型](https://docs.qq.com/sheet/DVnpkTnF6VW9UeXdh?c=A1A0A0)的自动下载; -- 提供多种神经网络组件以及复现模型(涵盖中文分词、命名实体识别、句法分析、文本分类、文本匹配、指代消解、摘要等任务); -- Trainer提供多种内置Callback函数,方便实验记录、异常捕获等。 - -## 安装指南 - -fastNLP 依赖以下包: +[//]: # ([![codecov](https://codecov.io/gh/fastnlp/fastNLP/branch/master/graph/badge.svg)](https://codecov.io/gh/fastnlp/fastNLP)) -+ numpy>=1.14.2 -+ torch>=1.0.0 -+ tqdm>=4.28.1 -+ nltk>=3.4.1 -+ requests -+ spacy -+ prettytable>=0.7.2 +[//]: # ([![Pypi](https://img.shields.io/pypi/v/fastNLP.svg)](https://pypi.org/project/fastNLP)) -其中torch的安装可能与操作系统及 CUDA 的版本相关,请参见 [PyTorch 官网](https://pytorch.org/) 。 -在依赖包安装完成后,您可以在命令行执行如下指令完成安装 - -```shell -pip install fastNLP -python -m spacy download en -``` +[//]: # (![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)) +[//]: # ([![Documentation Status](https://readthedocs.org/projects/fastnlp/badge/?version=latest)](http://fastnlp.readthedocs.io/?badge=latest)) -## fastNLP教程 -中文[文档](https://fastnlp.readthedocs.io/)、[教程](https://fastnlp.readthedocs.io/zh/latest/user/tutorials.html) -### 快速入门 +fastNLP是一款轻量级的自然语言处理(NLP)工具包,目标是减少用户项目中的工程型代码,例如数据处理循环、训练循环、多卡运行等。 -- [0. 快速入门](https://fastnlp.readthedocs.io/zh/latest/user/quickstart.html) - -### 详细使用教程 - -- [1. 使用DataSet预处理文本](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_1_data_preprocess.html) -- [2. 使用Vocabulary转换文本与index](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_2_vocabulary.html) -- [3. 使用Embedding模块将文本转成向量](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_3_embedding.html) -- [4. 使用Loader和Pipe加载并处理数据集](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_4_load_dataset.html) -- [5. 动手实现一个文本分类器I-使用Trainer和Tester快速训练和测试](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_5_loss_optimizer.html) -- [6. 动手实现一个文本分类器II-使用DataSetIter实现自定义训练过程](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_6_datasetiter.html) -- [7. 使用Metric快速评测你的模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_7_metrics.html) -- [8. 使用Modules和Models快速搭建自定义模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_8_modules_models.html) -- [9. 快速实现序列标注模型](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_9_seq_labeling.html) -- [10. 使用Callback自定义你的训练过程](https://fastnlp.readthedocs.io/zh/latest/tutorials/tutorial_10_callback.html) - -### 扩展教程 - -- [Extend-1. BertEmbedding的各种用法](https://fastnlp.readthedocs.io/zh/latest/tutorials/extend_1_bert_embedding.html) -- [Extend-2. 分布式训练简介](https://fastnlp.readthedocs.io/zh/latest/tutorials/extend_2_dist.html) -- [Extend-3. 使用fitlog 辅助 fastNLP 进行科研](https://fastnlp.readthedocs.io/zh/latest/tutorials/extend_3_fitlog.html) +fastNLP具有如下的特性: +- 便捷。在数据处理中可以通过apply函数避免循环、使用多进程提速等;在训练循环阶段可以很方便定制操作。 +- 高效。无需改动代码,实现fp16切换、多卡、ZeRO优化等。 +- 兼容。fastNLP支持多种深度学习框架作为后端。 -## 内置组件 +> :warning: **为了实现对不同深度学习架构的兼容,fastNLP 1.0.0之后的版本重新设计了架构,因此与过去的fastNLP版本不完全兼容, +> 基于更早的fastNLP代码需要做一定的调整**: -大部分用于的 NLP 任务神经网络都可以看做由词嵌入(embeddings)和两种模块:编码器(encoder)、解码器(decoder)组成。 +## 安装指南 +fastNLP可以通过以下的命令进行安装 +```shell +pip install fastNLP +``` +如果需要安装更早版本的fastNLP请指定版本号,例如 +```shell +pip install fastNLP==0.7.1 +``` +另外,请根据使用的深度学习框架,安装相应的深度学习框架。 + +
    +Pytorch +下面是使用pytorch来进行文本分类的例子。需要安装torch>=1.6.0。 + +```python +from fastNLP.io import ChnSentiCorpLoader +from functools import partial +from fastNLP import cache_results +from fastNLP.transformers.torch import BertTokenizer + +# 使用cache_results装饰器装饰函数,将prepare_data的返回结果缓存到caches/cache.pkl,再次运行时,如果 +# 该文件还存在,将自动读取缓存文件,而不再次运行预处理代码。 +@cache_results('caches/cache.pkl') +def prepare_data(): + # 会自动下载 SST2 数据,并且可以通过文档看到返回的 dataset 应该是包含"raw_words"和"target"两个field的 + data_bundle = ChnSentiCorpLoader().load() + # 使用tokenizer对数据进行tokenize + tokenizer = BertTokenizer.from_pretrained('hfl/chinese-bert-wwm') + tokenize = partial(tokenizer, max_length=256) # 限制数据的最大长度 + data_bundle.apply_field_more(tokenize, field_name='raw_chars', num_proc=4) # 会新增"input_ids", "attention_mask"等field进入dataset中 + data_bundle.apply_field(int, field_name='target', new_field_name='labels') # 将int函数应用到每个target上,并且放入新的labels field中 + return data_bundle +data_bundle = prepare_data() +print(data_bundle.get_dataset('train')[:4]) + +# 初始化model, optimizer +from fastNLP.transformers.torch import BertForSequenceClassification +from torch import optim +model = BertForSequenceClassification.from_pretrained('hfl/chinese-bert-wwm') +optimizer = optim.AdamW(model.parameters(), lr=2e-5) + +# 准备dataloader +from fastNLP import prepare_dataloader +dls = prepare_dataloader(data_bundle, batch_size=32) + +# 准备训练 +from fastNLP import Trainer, Accuracy, LoadBestModelCallback, TorchWarmupCallback, Event +callbacks = [ + TorchWarmupCallback(warmup=0.1, schedule='linear'), # 训练过程中调整学习率。 + LoadBestModelCallback() # 将在训练结束之后,加载性能最优的model +] +# 在训练特定时机加入一些操作, 不同时机能够获取到的参数不一样,可以通过Trainer.on函数的文档查看每个时机的参数 +@Trainer.on(Event.on_before_backward()) +def print_loss(trainer, outputs): + if trainer.global_forward_batches % 10 == 0: # 每10个batch打印一次loss。 + print(outputs.loss.item()) + +trainer = Trainer(model=model, train_dataloader=dls['train'], optimizers=optimizer, + device=0, evaluate_dataloaders=dls['dev'], metrics={'acc': Accuracy()}, + callbacks=callbacks, monitor='acc#acc',n_epochs=5, + # Accuracy的update()函数需要pred,target两个参数,它们实际对应的就是以下的field。 + evaluate_input_mapping={'labels': 'target'}, # 在评测时,将dataloader中会输入到模型的labels重新命名为target + evaluate_output_mapping={'logits': 'pred'} # 在评测时,将model输出中的logits重新命名为pred + ) +trainer.run() + +# 在测试集合上进行评测 +from fastNLP import Evaluator +evaluator = Evaluator(model=model, dataloaders=dls['test'], metrics={'acc': Accuracy()}, + # Accuracy的update()函数需要pred,target两个参数,它们实际对应的就是以下的field。 + output_mapping={'logits': 'pred'}, + input_mapping={'labels': 'target'}) +evaluator.run() +``` -以文本分类任务为例,下图展示了一个BiLSTM+Attention实现文本分类器的模型流程图: +
    + +
    +Paddle +下面是使用paddle来进行文本分类的例子。需要安装paddle>=2.2.0以及paddlenlp>=2.3.3。 + +```python +from fastNLP.io import ChnSentiCorpLoader +from functools import partial + +# 会自动下载 SST2 数据,并且可以通过文档看到返回的 dataset 应该是包含"raw_words"和"target"两个field的 +data_bundle = ChnSentiCorpLoader().load() + +# 使用tokenizer对数据进行tokenize +from paddlenlp.transformers import BertTokenizer +tokenizer = BertTokenizer.from_pretrained('hfl/chinese-bert-wwm') +tokenize = partial(tokenizer, max_length=256) # 限制一下最大长度 +data_bundle.apply_field_more(tokenize, field_name='raw_chars', num_proc=4) # 会新增"input_ids", "attention_mask"等field进入dataset中 +data_bundle.apply_field(int, field_name='target', new_field_name='labels') # 将int函数应用到每个target上,并且放入新的labels field中 +print(data_bundle.get_dataset('train')[:4]) + +# 初始化 model +from paddlenlp.transformers import BertForSequenceClassification, LinearDecayWithWarmup +from paddle import optimizer, nn +class SeqClsModel(nn.Layer): + def __init__(self, model_checkpoint, num_labels): + super(SeqClsModel, self).__init__() + self.num_labels = num_labels + self.bert = BertForSequenceClassification.from_pretrained(model_checkpoint) + + def forward(self, input_ids, token_type_ids=None, position_ids=None, attention_mask=None): + logits = self.bert(input_ids, token_type_ids, position_ids, attention_mask) + return logits + + def train_step(self, input_ids, labels, token_type_ids=None, position_ids=None, attention_mask=None): + logits = self(input_ids, token_type_ids, position_ids, attention_mask) + loss_fct = nn.CrossEntropyLoss() + loss = loss_fct(logits.reshape((-1, self.num_labels)), labels.reshape((-1, ))) + return { + "logits": logits, + "loss": loss, + } + + def evaluate_step(self, input_ids, token_type_ids=None, position_ids=None, attention_mask=None): + logits = self(input_ids, token_type_ids, position_ids, attention_mask) + return { + "logits": logits, + } + +model = SeqClsModel('hfl/chinese-bert-wwm', num_labels=2) + +# 准备dataloader +from fastNLP import prepare_dataloader +dls = prepare_dataloader(data_bundle, batch_size=16) + +# 训练过程中调整学习率。 +scheduler = LinearDecayWithWarmup(2e-5, total_steps=20 * len(dls['train']), warmup=0.1) +optimizer = optimizer.AdamW(parameters=model.parameters(), learning_rate=scheduler) + +# 准备训练 +from fastNLP import Trainer, Accuracy, LoadBestModelCallback, Event +callbacks = [ + LoadBestModelCallback() # 将在训练结束之后,加载性能最优的model +] +# 在训练特定时机加入一些操作, 不同时机能够获取到的参数不一样,可以通过Trainer.on函数的文档查看每个时机的参数 +@Trainer.on(Event.on_before_backward()) +def print_loss(trainer, outputs): + if trainer.global_forward_batches % 10 == 0: # 每10个batch打印一次loss。 + print(outputs["loss"].item()) + +trainer = Trainer(model=model, train_dataloader=dls['train'], optimizers=optimizer, + device=0, evaluate_dataloaders=dls['dev'], metrics={'acc': Accuracy()}, + callbacks=callbacks, monitor='acc#acc', + # Accuracy的update()函数需要pred,target两个参数,它们实际对应的就是以下的field。 + evaluate_output_mapping={'logits': 'pred'}, + evaluate_input_mapping={'labels': 'target'} + ) +trainer.run() + +# 在测试集合上进行评测 +from fastNLP import Evaluator +evaluator = Evaluator(model=model, dataloaders=dls['test'], metrics={'acc': Accuracy()}, + # Accuracy的update()函数需要pred,target两个参数,它们实际对应的就是以下的field。 + output_mapping={'logits': 'pred'}, + input_mapping={'labels': 'target'}) +evaluator.run() +``` +
    -![](./docs/source/figures/text_classification.png) +
    +oneflow +
    -fastNLP 在 embeddings 模块中内置了几种不同的embedding:静态embedding(GloVe、word2vec)、上下文相关embedding -(ELMo、BERT)、字符embedding(基于CNN或者LSTM的CharEmbedding) -与此同时,fastNLP 在 modules 模块中内置了两种模块的诸多组件,可以帮助用户快速搭建自己所需的网络。 两种模块的功能和常见组件如下: - - - - - - - - - - - - - - - -
    类型 功能 例子
    encoder 将输入编码为具有具有表示能力的向量 Embedding, RNN, CNN, Transformer, ... -
    decoder 将具有某种表示意义的向量解码为需要的输出形式 MLP, CRF, ...
    +
    +jittor +
    ## 项目结构 -
    - - - -fastNLP的大致工作流程如上图所示,而项目结构如下: +fastNLP的项目结构如下: @@ -135,4 +233,3 @@ fastNLP的大致工作流程如上图所示,而项目结构如下:
    -*In memory of @FengZiYjun. May his soul rest in peace. We will miss you very very much!* diff --git a/fastNLP/core/callbacks/more_evaluate_callback.py b/fastNLP/core/callbacks/more_evaluate_callback.py index 04b35984..26de0a04 100644 --- a/fastNLP/core/callbacks/more_evaluate_callback.py +++ b/fastNLP/core/callbacks/more_evaluate_callback.py @@ -127,10 +127,6 @@ class MoreEvaluateCallback(HasMonitorCallback): assert trainer.evaluator is not None, f"You set `watch_monitor={self.monitor}`, but no " \ f"evaluate_dataloaders is provided in Trainer." - if trainer.evaluate_fn is self.evaluate_fn: - logger.warning_once("The `evaluate_fn` is the same as in Trainer, there seems no need to use " - "`MoreEvaluateCallback`.") - # 初始化 evaluator , 同时避免调用 super 对 monitor 赋值 kwargs = { 'model': self.kwargs.get('model', trainer.model), diff --git a/fastNLP/core/callbacks/torch_callbacks/torch_lr_sched_callback.py b/fastNLP/core/callbacks/torch_callbacks/torch_lr_sched_callback.py index 24474b64..07c3c612 100644 --- a/fastNLP/core/callbacks/torch_callbacks/torch_lr_sched_callback.py +++ b/fastNLP/core/callbacks/torch_callbacks/torch_lr_sched_callback.py @@ -18,7 +18,7 @@ class TorchWarmupCallback(Callback): 1. *linear* -- 前 ``warmup`` 的 step 上升到指定的学习率(从 Trainer 中 optimizer 处获取), 在剩下的 step 中下降到 0; 2. *constant* -- 前 ``warmup`` 的 step 上升到指定的学习率,余下的 step 保持不变。 """ - def __init__(self, warmup:Union[int, float]=0.1, schedule:str='constant'): + def __init__(self, warmup:Union[int, float]=0.1, schedule:str='linear'): super().__init__() self.warmup = max(warmup, 0.) diff --git a/fastNLP/core/controllers/evaluator.py b/fastNLP/core/controllers/evaluator.py index 96ba5833..597d13de 100644 --- a/fastNLP/core/controllers/evaluator.py +++ b/fastNLP/core/controllers/evaluator.py @@ -42,7 +42,8 @@ class Evaluator: ``Trainer`` 中的参数相同,对于这些参数,您可以参考 ``Trainer`` 的文档来获取更详细的信息;详见 :class:`~fastNLP.core.controllers.trainer.Trainer`; :param model: 训练所需要的模型,例如 ``torch.nn.Module``,等价于 ``Trainer`` 中的 ``model`` 参数; - :param dataloaders: 用于评测的数据集。如果为多个,您需要使用 ``dict`` 传入,即对每一个数据集标上用于标识它们的标签; + :param dataloaders: 用于评测的数据集。如果为多个,您需要使用 ``dict`` 传入,即对每一个数据集标上用于标识它们的标签;也可以使用 evaluate_dataloaders + 作为参数的名称。 :param metrics: 评测时使用的指标。注意该参数必须为 ``dict`` 类型,其中 ``key`` 为一个 ``metric`` 的名称,``value`` 为具体的 ``Metric`` 对象。目前支持以下 metrics: 1. fastNLP 自己的 ``metric``:详见 :class:`~fastNLP.core.metrics.Metric`; @@ -82,13 +83,14 @@ class Evaluator: 2. 如果为 ``str`` 类型,例如为 ``'my_evaluate_step_fn'``,则尝试寻找 :meth:`model.my_evaluate_step_fn`,如果找不到则直接报错; :param input_mapping: 等价于 ``Trainer`` 中的 ``input_mapping`` 参数;对具体的用于评测一个 batch 的数据使用 ``input_mapping`` 处理之后再输入到 ``model`` 以及 ``metric`` 中。如果针对 - ``model`` 和 ``metric`` 需要不同的 ``mapping``,请考虑使用 ``evaluate_batch_step_fn`` 参数定制; + ``model`` 和 ``metric`` 需要不同的 ``mapping``,请考虑使用 ``evaluate_batch_step_fn`` 参数定制;也可以使用 evaluate_input_mapping 参数名传入。 .. todo:: 之后链接上 参数匹配 的文档; :param output_mapping: 等价于 ``Trainer`` 中的 ``output_mapping`` 参数;对 ``model`` 输出的内容,将通过 ``output_mapping`` 处理之后再输入到 ``metric`` 中; + 也可以使用 evaluate_output_mapping 参数名传入。 :param model_wo_auto_param_call: 等价于 ``Trainer`` 中的 ``model_wo_auto_param_call`` 参数; .. note:: @@ -128,7 +130,7 @@ class Evaluator: driver: Driver _evaluate_batch_loop: Loop - def __init__(self, model, dataloaders, metrics: Optional[Dict] = None, + def __init__(self, model, dataloaders=None, metrics: Optional[Dict] = None, driver: Union[str, Driver] = 'auto', device: Optional[Union[int, List[int], str]] = None, evaluate_batch_step_fn: Optional[Callable] = None, evaluate_fn: Optional[str] = None, input_mapping: Optional[Union[Callable, Dict]] = None, @@ -139,6 +141,7 @@ class Evaluator: self.driver = choose_driver(model, driver, device, fp16=fp16, model_wo_auto_param_call=model_wo_auto_param_call, **kwargs) + dataloaders = dataloaders if dataloaders is not None else kwargs.get('evaluate_dataloaders') if dataloaders is None: raise ValueError("Parameter `dataloaders` can not be None.") self.dataloaders = dataloaders @@ -151,8 +154,8 @@ class Evaluator: _check_valid_parameters_number(evaluate_batch_step_fn, ['evaluator', 'batch'], fn_name='evaluate_batch_step_fn') self.evaluate_batch_step_fn = evaluate_batch_step_fn - self.input_mapping = input_mapping - self.output_mapping = output_mapping + self.input_mapping = input_mapping if input_mapping is not None else kwargs.get('evaluate_input_mapping') + self.output_mapping = output_mapping if output_mapping is not None else kwargs.get('evaluate_output_mapping') # check dataloader if not isinstance(dataloaders, dict): diff --git a/fastNLP/core/controllers/trainer.py b/fastNLP/core/controllers/trainer.py index 8a0b25ac..454db3d0 100644 --- a/fastNLP/core/controllers/trainer.py +++ b/fastNLP/core/controllers/trainer.py @@ -595,7 +595,7 @@ class Trainer(TrainerEventTrigger): :param resume_from: 从哪个路径下恢复 trainer 的状态,注意该值需要为一个文件夹,例如使用 ``CheckpointCallback`` 时帮助您创建的保存的子文件夹; :param resume_training: 是否按照 checkpoint 中训练状态恢复。如果为 False,则只恢复 model 和 optimizers 的状态;该参数如果为 ``True``, 在下一次断点重训的时候我们会精确到上次训练截止的具体的 sample 进行训练;否则我们只会恢复 model 和 optimizers 的状态,而 ``Trainer`` 中的 - 其余状态都是保持初始化时的状态不会改变; + 其余状态都是保持初始化时的状态不会改变。仅当传入了 resume_from 参数时有意义。 :param catch_KeyboardInterrupt: 是否捕获 :class:`KeyboardInterrupt`;如果该参数为 ``True``,在训练时如果您使用 ``ctrl+c`` 来终止程序, ``Trainer`` 不会抛出异常,但是会提前退出,然后 ``trainer.run()`` 之后的代码会继续运行。注意该参数在您使用分布式训练的 ``Driver`` 时无效,例如 ``TorchDDPDriver``;非分布式训练的 ``Driver`` 下该参数默认为 True; diff --git a/fastNLP/core/dataloaders/oneflow_dataloader/fdl.py b/fastNLP/core/dataloaders/oneflow_dataloader/fdl.py index 1dd40500..15fea5d4 100644 --- a/fastNLP/core/dataloaders/oneflow_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/oneflow_dataloader/fdl.py @@ -287,6 +287,8 @@ def prepare_oneflow_dataloader(ds_or_db, from fastNLP.io import DataBundle if isinstance(ds_or_db, DataBundle): + assert sampler is None, "sampler can only be None when multiple datasets are presented." + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." dl_bundle = {} for name, ds in ds_or_db.iter_datasets(): if 'train' in name: @@ -313,6 +315,8 @@ def prepare_oneflow_dataloader(ds_or_db, return dl_bundle elif isinstance(ds_or_db, Mapping): + assert sampler is None, "sampler can only be None when multiple datasets are presented." + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." dl_bundle = {} for name, ds in ds_or_db.items(): if 'train' in name: diff --git a/fastNLP/core/dataloaders/paddle_dataloader/fdl.py b/fastNLP/core/dataloaders/paddle_dataloader/fdl.py index 549e6c36..529f23aa 100644 --- a/fastNLP/core/dataloaders/paddle_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/paddle_dataloader/fdl.py @@ -320,6 +320,7 @@ def prepare_paddle_dataloader(ds_or_db, feed_list=None, places=None, from fastNLP.io.data_bundle import DataBundle if isinstance(ds_or_db, DataBundle): + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." dl_bundle = {} for name, ds in ds_or_db.iter_datasets(): if 'train' in name: @@ -346,6 +347,7 @@ def prepare_paddle_dataloader(ds_or_db, feed_list=None, places=None, return dl_bundle elif isinstance(ds_or_db, Dict): + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." ds_dict = {} for name, ds in ds_or_db.items(): if 'train' in name: diff --git a/fastNLP/core/dataloaders/torch_dataloader/fdl.py b/fastNLP/core/dataloaders/torch_dataloader/fdl.py index 3bba0476..5ae72367 100644 --- a/fastNLP/core/dataloaders/torch_dataloader/fdl.py +++ b/fastNLP/core/dataloaders/torch_dataloader/fdl.py @@ -287,6 +287,8 @@ def prepare_torch_dataloader(ds_or_db, from fastNLP.io import DataBundle if isinstance(ds_or_db, DataBundle): + assert sampler is None, "sampler can only be None when multiple datasets are presented." + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." dl_bundle = {} for name, ds in ds_or_db.iter_datasets(): if 'train' in name: @@ -313,6 +315,8 @@ def prepare_torch_dataloader(ds_or_db, return dl_bundle elif isinstance(ds_or_db, Mapping): + assert sampler is None, "sampler can only be None when multiple datasets are presented." + assert batch_sampler is None, "batch_sampler can only be None when multiple datasets are presented." dl_bundle = {} for name, ds in ds_or_db.items(): if 'train' in name: diff --git a/fastNLP/core/metrics/accuracy.py b/fastNLP/core/metrics/accuracy.py index 7af788ce..5475046e 100644 --- a/fastNLP/core/metrics/accuracy.py +++ b/fastNLP/core/metrics/accuracy.py @@ -34,8 +34,7 @@ class Accuracy(Metric): :return: 包含以下内容的字典:``{"acc": float, 'total': float, 'correct': float}``; """ - evaluate_result = {'acc': round(self.correct.get_scalar() / (self.total.get_scalar() + 1e-12), 6), - 'total': self.total.item(), 'correct': self.correct.item()} + evaluate_result = {'acc': round(self.correct.get_scalar() / (self.total.get_scalar() + 1e-12), 6)} return evaluate_result def update(self, pred, target, seq_len=None): diff --git a/fastNLP/core/metrics/span_f1_pre_rec_metric.py b/fastNLP/core/metrics/span_f1_pre_rec_metric.py index 5ec8b9ad..a3c5a722 100644 --- a/fastNLP/core/metrics/span_f1_pre_rec_metric.py +++ b/fastNLP/core/metrics/span_f1_pre_rec_metric.py @@ -328,7 +328,7 @@ class SpanFPreRecMetric(Metric): return evaluate_result - def update(self, pred, target, seq_len: Optional[List] = None) -> None: + def update(self, pred, target, seq_len) -> None: r""" :meth:`update` 函数将针对一个批次的预测结果做评价指标的累计。 diff --git a/fastNLP/core/vocabulary.py b/fastNLP/core/vocabulary.py index 4bcc6e3b..3a6ab650 100644 --- a/fastNLP/core/vocabulary.py +++ b/fastNLP/core/vocabulary.py @@ -349,15 +349,18 @@ class Vocabulary(object): for idx, dataset in enumerate(datasets): if isinstance(dataset, DataSet): - try: - for f_n, n_f_n in zip(field_name, new_field_name): - dataset.apply_field(index_instance, field_name=f_n, new_field_name=n_f_n, - progress_bar=None) - except Exception as e: - logger.error("When processing the `{}` dataset, the following error occurred.".format(idx)) - raise e + ds_lst = [dataset] + elif _is_iterable(dataset): + ds_lst = list(dataset) else: - raise RuntimeError("Only DataSet type is allowed.") + raise TypeError(f"Only DataSet type is allowed, instead of {type(dataset)}.") + try: + for ds in ds_lst: + for f_n, n_f_n in zip(field_name, new_field_name): + ds.apply_field(index_instance, field_name=f_n, new_field_name=n_f_n, progress_bar=None) + except Exception as e: + logger.error("When processing the `{}` dataset, the following error occurred.".format(idx)) + raise e return self @property @@ -408,13 +411,18 @@ class Vocabulary(object): for idx, dataset in enumerate(datasets): if isinstance(dataset, DataSet): - try: - dataset.apply(construct_vocab, progress_bar=None) - except BaseException as e: - logger.error("When processing the `{}` dataset, the following error occurred:".format(idx)) - raise e + ds_lst = [dataset] + elif _is_iterable(dataset): + ds_lst = list(dataset) else: - raise TypeError("Only DataSet type is allowed.") + raise TypeError(f"Only DataSet type is allowed, instead of {type(dataset)}.") + + try: + for ds in ds_lst: + ds.apply(construct_vocab, progress_bar=None) + except BaseException as e: + logger.error("When processing the `{}` dataset, the following error occurred:".format(idx)) + raise e if no_create_entry_dataset is not None: partial_construct_vocab = partial(construct_vocab, no_create_entry=True) diff --git a/fastNLP/io/data_bundle.py b/fastNLP/io/data_bundle.py index 69e092cc..03e58e56 100644 --- a/fastNLP/io/data_bundle.py +++ b/fastNLP/io/data_bundle.py @@ -6,7 +6,7 @@ __all__ = [ 'DataBundle', ] -from typing import Union, List, Callable +from typing import Union, List, Callable, Dict from ..core.dataset import DataSet from fastNLP.core.vocabulary import Vocabulary @@ -29,8 +29,16 @@ class DataBundle: """ def __init__(self, vocabs=None, datasets=None): - self.vocabs = vocabs or {} - self.datasets = datasets or {} + self._vocabs = vocabs or {} + self._datasets = datasets or {} + + @property + def datasets(self)->Dict: + return self._datasets + + @property + def vocabs(self) -> Dict: + return self._vocabs def set_vocab(self, vocab: Vocabulary, field_name: str): r""" diff --git a/fastNLP/io/utils.py b/fastNLP/io/utils.py index 57a283ba..a3af71f5 100644 --- a/fastNLP/io/utils.py +++ b/fastNLP/io/utils.py @@ -55,16 +55,16 @@ def check_loader_paths(paths: Union[str, Dict[str, str]]) -> Dict[str, str]: raise FileExistsError(f"Two files contain `{path_pair[0]}` were found, please specify the " f"filepath for `{path_pair[0]}`.") files[path_pair[0]] = os.path.join(paths, path_pair[1]) - if 'train' not in files: - raise KeyError(f"There is no train file in {paths}.") + # if 'train' not in files: + # raise KeyError(f"There is no train file in {paths}.") return files else: raise FileNotFoundError(f"{paths} is not a valid file path.") elif isinstance(paths, dict): if paths: - if 'train' not in paths: - raise KeyError("You have to include `train` in your dict.") + # if 'train' not in paths: + # raise KeyError("You have to include `train` in your dict.") for key, value in paths.items(): if isinstance(key, str) and isinstance(value, str): value = os.path.abspath(os.path.expanduser(value)) diff --git a/setup.py b/setup.py index cde5680c..029c8696 100644 --- a/setup.py +++ b/setup.py @@ -16,14 +16,14 @@ print(pkgs) setup( name='FastNLP', - version='0.8.0alpha', + version='1.0.0alpha', url='https://gitee.com/fastnlp/fastNLP', description='fastNLP: Deep Learning Toolkit for NLP, developed by Fudan FastNLP Team', long_description=readme, long_description_content_type='text/markdown', license='Apache License', author='Fudan FastNLP Team', - python_requires='>=3.7', + python_requires='>=3.6', packages=pkgs, install_requires=reqs.strip().split('\n'), )
  • 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 z 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