Browse Source

增加voc, dl的文档

tags/v1.0.0alpha
MorningForest 3 years ago
parent
commit
5945c3f909
5 changed files with 188 additions and 77 deletions
  1. +21
    -9
      fastNLP/core/dataloaders/jittor_dataloader/fdl.py
  2. +2
    -2
      fastNLP/core/dataloaders/mix_dataloader.py
  3. +78
    -1
      fastNLP/core/dataloaders/paddle_dataloader/fdl.py
  4. +87
    -65
      fastNLP/core/vocabulary.py
  5. +0
    -0
      pad_val

+ 21
- 9
fastNLP/core/dataloaders/jittor_dataloader/fdl.py View File

@@ -21,7 +21,7 @@ from fastNLP.core.dataset import DataSet as FDataSet


class _JittorDataset(Dataset): class _JittorDataset(Dataset):
""" """
对用户传的dataset进行封装,以便JittorDataLoader能够支持使用自定义的dataset使用jittor的dataset
对用户传的dataset进行封装,以便JittorDataLoader能够支持使用自定义的dataset
""" """


def __init__(self, dataset) -> None: def __init__(self, dataset) -> None:
@@ -35,7 +35,10 @@ class _JittorDataset(Dataset):


class JittorDataLoader: class JittorDataLoader:
""" """
提供给使用jittor框架的DataLoader函数,提供了auto_collate的功能, 支持实现了__getitem__和__len__的dataset
提供给使用jittor框架的DataLoader函数,其能够自动检测数据的类型并判断是否能够pad,若能会自动pad数据,默认pad_val=0;
用户可以调用set_pad方法来更改pad_val的值,也可以自定义针对某个field的callate_fn传入到set_field;若用户不想自动pad某个field,
则可以调用set_ignore来忽略对某个field的检测和pad。值得注意的是JittorDataLoader输入dataset只要是实现了__getitem__和__len__方法即可。

""" """


def __init__(self, dataset, batch_size: int = 16, shuffle: bool = False, def __init__(self, dataset, batch_size: int = 16, shuffle: bool = False,
@@ -44,16 +47,25 @@ class JittorDataLoader:
collate_fn: Union[None, str, Callable] = "auto") -> None: collate_fn: Union[None, str, Callable] = "auto") -> None:
""" """


:param dataset: 实现__getitem__和__len__的dataset
:param dataset: 实现``__getitem__````__len__``的dataset
:param batch_size: 批次大小 :param batch_size: 批次大小
:param shuffle: 是否打乱数据集 :param shuffle: 是否打乱数据集
:param drop_last: 是否去掉最后一个不符合batch_size的数据
:param num_workers: 进程的数量,当num_workers=0时不开启多进程
:param buffer_size:
:param drop_last: 是否去掉最后一个不符合``batch_size``的数据
:param num_workers: 进程的数量,当``num_workers=0``时不开启多进程
:param buffer_size: 每个进程占用的内存空间,默认为512M。主要是配合num_workers使用,用户可以自定义每个进程的内存大小。
:param stop_grad: :param stop_grad:
:param keep_numpy_array:
:param endless:
:param collate_fn: 对取得到的数据进行打包的callable函数
:param keep_numpy_array: 返回的数据是``np.array`类`型而不是``jittor.array``类型,默认为``False``
:param endless: 是否让``JittorDataLoader``无限返回数据,也就是将dataset循环使用使得返回数据是没有限制的。默认为``False``.
:param collate_fn: 用来对从dataset取到的数据进行打包处理成batch的callable函数,其值应该为一下三个:``[None, "auto", callable]``.

* ``callate_fn=None``时,第一点值得注意的是此时传进来的datset不能为``fastNLP``的dataset,采用fastNLP的dataset时,``collate_fn``不能为``None``;
第二点注意的是此时``JittorDataLoader``会调用默认的`callate_batch`函数对sampler到的数据进行简单打包,组成一个batch返回。`
* ``callate_fn="auto"``时,``JittorDataLoader``会自动调用``fastNLP``自带的``Collator``,其会自动检测dataset的每个``field``,
并判断是否能够pad处理,若能则会自动进行pad操作,默认``pad_val=0``。若想要更改其值,可调用``set_pad``方法;若不想自动pad某个field,
可以调用``set_ignore``方法忽略某个field。
* ``callate_fn=callable``时,callable函数是用户自定义的callate_fn函数,此时``JittorDataLoader``会调用传进来的callable函数对
数据进行打包处理并返回。值得注意的是用户自定义的callable函数的输入为batch,batch为list类型数据,其中batch的每一条数据都为dataset的一条数据。

""" """
# TODO 验证支持replacesampler (以后完成) 增加Sampler # TODO 验证支持replacesampler (以后完成) 增加Sampler
# 将内部dataset批次设置为1 # 将内部dataset批次设置为1


+ 2
- 2
fastNLP/core/dataloaders/mix_dataloader.py View File

@@ -23,7 +23,6 @@ class _MixDataset:
""" """
def __init__(self, datasets: list = None) -> None: def __init__(self, datasets: list = None) -> None:
""" """

:param datasets: 数据集的列表 :param datasets: 数据集的列表
""" """
self.datasets = datasets self.datasets = datasets
@@ -36,8 +35,9 @@ class _MixDataset:


def __getitem__(self, idx: Union[int, List[int]]) -> Union[Tuple[Instance, int], Tuple[DataSet, int]]: def __getitem__(self, idx: Union[int, List[int]]) -> Union[Tuple[Instance, int], Tuple[DataSet, int]]:
""" """
根据index索引获取数据


:param idx:
:param idx: 整数类型的index或者列表
:return: :return:
""" """
if isinstance(idx, int): if isinstance(idx, int):


+ 78
- 1
fastNLP/core/dataloaders/paddle_dataloader/fdl.py View File

@@ -1,3 +1,31 @@
"""
``PaddleDataLoader``是专门提供给``paddle``框架的``DataLoader``,其集成了``fastNLP``的``Collator``并对``paddle``的``DataLoader``进行了
封装,使得其具备以下功能:1.``PaddleDataLoader``支持输入的dataset是无框架的,只要实现了``__getitem__``和``__len__``方法即可,当不使用``fastNLP``的
``DataSet``时候也能够自动检测数据的类型并进行padding,只需要将``collate_fn="auto"``即可,例如::

from fastNLP import PaddleDataLoader
class MyDataset:
def __init(self, data_lens=100):
self.data_lens = 100
def __getitem__(self, item):
if item % 2 == 0:
return {'x':[101, 256, 453], 'y': 0}
else:
return {'x': [101, 200], 'y': 1}
def __len__(self):
return self.data_lens
dataset = MyDataset()
paddle_dl = PaddleDataLoader(dataset, collate_fn="auto")
for batch in paddle_dl:
...

2.当设置``collate_fn="auto"``时,``PaddleDataLoader``会调用fastNLP的Collator对数据进行自动pad处理,此时可以调用``set_pad``和``set_ignore``方法
来设置field的pad_val或者忽略某个field的pad操作。
.. note::
当传入的dataset为fastNLP的DataSet时,collate_fn不能为None。默认可以是"auto"或者自定义callable函数。

"""

__all__ = [ __all__ = [
'PaddleDataLoader', 'PaddleDataLoader',
'prepare_paddle_dataloader' 'prepare_paddle_dataloader'
@@ -23,7 +51,7 @@ from fastNLP.core.samplers import ReproducibleBatchSampler, RandomBatchSampler


class _PaddleDataset(Dataset): class _PaddleDataset(Dataset):
""" """
对用户传的dataset进行封装,以便Fdataloader能够支持使用自定义的dataset使用paddle的dataloader
对用户传的dataset进行封装,以便PaddleDataLoader能够支持使用自定义的dataset
""" """


def __init__(self, dataset) -> None: def __init__(self, dataset) -> None:
@@ -44,6 +72,10 @@ class _PaddleDataset(Dataset):




class PaddleDataLoader(DataLoader): class PaddleDataLoader(DataLoader):
"""
提供给``paddle``框架使用的``DataLoader``函数,``PaddleDataLoader``提供了``Collator``的功能,用户可以通过设置``collate_fn="auto"``来
使用,并可以配套使用``set_pad``和``set_ignore``方法设置p``ad_val``和忽略某个field的pad操作。
"""


def __init__(self, dataset, feed_list=None, places=None, def __init__(self, dataset, feed_list=None, places=None,
return_list: bool = True, batch_sampler=None, return_list: bool = True, batch_sampler=None,
@@ -52,6 +84,51 @@ class PaddleDataLoader(DataLoader):
num_workers: int = 0, use_buffer_reader: bool = True, num_workers: int = 0, use_buffer_reader: bool = True,
use_shared_memory: bool = True, timeout: int = 0, use_shared_memory: bool = True, timeout: int = 0,
worker_init_fn: Callable = None, persistent_workers=False) -> None: worker_init_fn: Callable = None, persistent_workers=False) -> None:
"""

:param dataset: 实现了__getitem__和__len__的数据容器
:param feed_list: (list(Tensor)|tuple(Tensor)): feed Tensor list.
The Tensors should be created by :code:`paddle.static.data()`.
:attr:`feed_list` must be set if :attr:`return_list` is
False. Default None.
:param places: (list(Place)|tuple(Place)|list(str)|optional): a list of Place,
to put data onto, :attr:`places` can be None, if
:attr:`places` is None, default place(CPUPlace or CUDAPlace(0))
will be used. Default None. If ``places`` is list of string,
the string in the list can be ``cpu``, ``gpu:x`` and ``gpu_pinned``,
where ``x`` is the index of the GPUs.
:param return_list: whether the return value on each device is
presented as a list. If :attr:`return_list=False`, the return
value on each device would be a dict of str -> Tensor, where
the key of the dict is the name of each fed Tensors. If
:attr:`return_list=True`, the return value on each device would
be a list(Tensor). :attr:`return_list` can only be True
in dynamic graph mode. Default True.
:param batch_sampler: 实现了``__iter__``和``__len__``方法的实例化对象,它的功能是根据dataset生成数据indices并组成一个batch数据。
:param batch_size: dataloader每次获得数据的批次大小
:param shuffle: 是否将数据打乱,若``shuffle=True``则会将dataset打乱;若否则什么也不做。
:param drop_last: 当``drop_last=True``时,``PaddleDataLoader``会扔掉最后一个不能组成``batch_size``大小的batch数据;
若``drop_last=False``, 则什么也不做。
:param collate_fn:用来对从dataset取到的数据进行打包处理成batch的callable函数,其值应该为一下三个:``[None, "auto", callable]``.

* ``callate_fn=None``时,第一点值得注意的是此时传进来的datset不能为``fastNLP``的dataset,采用fastNLP的dataset时,``collate_fn``不能为``None``;
第二点注意的是此时``PaddleDataLoader``会调用默认的`default_collate_fn`函数对sampler到的数据进行简单打包,组成一个batch返回。`
* ``callate_fn="auto"``时,``PaddleDataLoader``会自动调用``fastNLP``自带的``Collator``,其会自动检测dataset的每个``field``,
并判断是否能够pad处理,若能则会自动进行pad操作,默认``pad_val=0``。若想要更改其值,可调用``set_pad``方法;若不想自动pad某个field,
可以调用``set_ignore``方法忽略某个field。
* ``callate_fn=callable``时,callable函数是用户自定义的callate_fn函数,此时``PaddleDataLoader``会调用传进来的callable函数对
数据进行打包处理并返回。值得注意的是用户自定义的callable函数的输入为batch,batch为list类型数据,其中batch的每一条数据都为dataset的一条数据。

:param num_workers: 开启多进程的数量,当``num_workers=0``时不开启多进程
:param use_buffer_reader: 是否开启buffer_reader。如果``use_buffer_reader=True``,那么``PaddleDataLoader``将会异步的预取下一个batch的
数据,因此它将会加快数据传输的速度,但是将会占用更多的内存或者显存。默认值是``True``。如果``use_buffer_reader=False``,那么什么也不错
:param use_shared_memory: 是否使用共享内存。当``use_shared_memory=True``时,将采用共享内存来加快将数据放进进程队列。建议仅当计算机上的
共享空间足够大时。(例如Linux上的/dev/shm/空间足够大)共享内存仅在多进程模式(num_workers>0)下生效。
:param timeout: 从子进程的输出队列获取数据的超时值
:param worker_init_fn: init函数,如果不设置为None,则将会在每个子进程初始化时调用该函数。
:param persistent_workers:

"""
# FastNLP Datset, collate_fn not None # FastNLP Datset, collate_fn not None
if isinstance(dataset, FDataSet) and collate_fn is None: if isinstance(dataset, FDataSet) and collate_fn is None:
raise ValueError("When use FastNLP DataSet, collate_fn must be not None") raise ValueError("When use FastNLP DataSet, collate_fn must be not None")


+ 87
- 65
fastNLP/core/vocabulary.py View File

@@ -11,6 +11,7 @@ __all__ = [
from collections import Counter from collections import Counter
from functools import partial from functools import partial
from functools import wraps from functools import wraps
from typing import List, Callable, Union


from fastNLP.core.dataset import DataSet from fastNLP.core.dataset import DataSet
from fastNLP.core.utils.utils import Option from fastNLP.core.utils.utils import Option
@@ -20,6 +21,9 @@ import io




class VocabularyOption(Option): class VocabularyOption(Option):
"""

"""
def __init__(self, def __init__(self,
max_size=None, max_size=None,
min_freq=None, min_freq=None,
@@ -33,8 +37,11 @@ class VocabularyOption(Option):
) )




def _check_build_vocab(func):
r"""A decorator to make sure the indexing is built before used.
def _check_build_vocab(func: Callable):
r"""
A decorator to make sure the indexing is built before used.

:param func: 传入的callable函数


""" """
@@ -48,7 +55,10 @@ def _check_build_vocab(func):




def _check_build_status(func): def _check_build_status(func):
r"""A decorator to check whether the vocabulary updates after the last build.
r"""
A decorator to check whether the vocabulary updates after the last build.

:param func: 用户传入要修饰的callable函数


""" """
@@ -69,27 +79,30 @@ class Vocabulary(object):
r""" r"""
用于构建, 存储和使用 `str` 到 `int` 的一一映射:: 用于构建, 存储和使用 `str` 到 `int` 的一一映射::


from fastNLP.core import Vocabulary
vocab = Vocabulary() vocab = Vocabulary()
word_list = "this is a word list".split() word_list = "this is a word list".split()
# vocab更新自己的字典,输入为list列表
vocab.update(word_list) vocab.update(word_list)
vocab["word"] # str to int vocab["word"] # str to int
vocab.to_word(5) # int to str vocab.to_word(5) # int to str

""" """
def __init__(self, max_size=None, min_freq=None, padding='<pad>', unknown='<unk>'):
def __init__(self, max_size:int=None, min_freq:int=None, padding:str='<pad>', unknown:str='<unk>'):
r""" r"""
:param int max_size: `Vocabulary` 的最大大小, 即能存储词的最大数量
:param max_size: `Vocabulary` 的最大大小, 即能存储词的最大数量
若为 ``None`` , 则不限制大小. Default: ``None`` 若为 ``None`` , 则不限制大小. Default: ``None``
:param int min_freq: 能被记录下的词在文本中的最小出现频率, 应大于或等于 1.
:param min_freq: 能被记录下的词在文本中的最小出现频率, 应大于或等于 1.
若小于该频率, 词语将被视为 `unknown`. 若为 ``None`` , 所有文本中的词都被记录. Default: ``None`` 若小于该频率, 词语将被视为 `unknown`. 若为 ``None`` , 所有文本中的词都被记录. Default: ``None``
:param str optional padding: padding的字符. 如果设置为 ``None`` ,
:param padding: padding的字符. 如果设置为 ``None`` ,
则vocabulary中不考虑padding, 也不计入词表大小,为 ``None`` 的情况多在为label建立Vocabulary的情况. 则vocabulary中不考虑padding, 也不计入词表大小,为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<pad>' Default: '<pad>'
:param str optional unknown: unknown的字符,所有未被记录的词在转为 `int` 时将被视为unknown.
:param unknown: unknown的字符,所有未被记录的词在转为 `int` 时将被视为unknown.
如果设置为 ``None`` ,则vocabulary中不考虑unknow, 也不计入词表大小. 如果设置为 ``None`` ,则vocabulary中不考虑unknow, 也不计入词表大小.
为 ``None`` 的情况多在为label建立Vocabulary的情况. 为 ``None`` 的情况多在为label建立Vocabulary的情况.
Default: '<unk>' Default: '<unk>'

""" """
self.max_size = max_size self.max_size = max_size
self.min_freq = min_freq self.min_freq = min_freq
@@ -121,45 +134,50 @@ class Vocabulary(object):
self._word2idx = value self._word2idx = value


@_check_build_status @_check_build_status
def update(self, word_lst, no_create_entry=False):
r"""依次增加序列中词在词典中的出现频率
def update(self, word_lst: list, no_create_entry:bool=False):
r"""
依次增加序列中词在词典中的出现频率


:param list word_lst: a list of strings
:param bool no_create_entry: 如果词语来自于非训练集建议设置为True。在使用fastNLP.TokenEmbedding加载预训练模型时,没有从预训练词表中找到这个词的处理方式。
:param word_lst: 列表形式的词语,如word_list=['I', 'am', 'a', 'Chinese'],列表中的每个词会计算出现频率并加入到词典中。
:param no_create_entry: 如果词语来自于非训练集建议设置为True。
如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独 如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独
的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新 的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新
加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这 加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这
个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的, 个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的,
则这个词将认为是需要创建单独的vector的。 则这个词将认为是需要创建单独的vector的。

""" """
self._add_no_create_entry(word_lst, no_create_entry) self._add_no_create_entry(word_lst, no_create_entry)
self.word_count.update(word_lst) self.word_count.update(word_lst)
return self return self
@_check_build_status @_check_build_status
def add(self, word, no_create_entry=False):
def add(self, word:str, no_create_entry:bool=False):
r""" r"""
增加一个新词在词典中的出现频率 增加一个新词在词典中的出现频率


:param str word: 新词
:param bool no_create_entry: 如果词语来自于非训练集建议设置为True。在使用fastNLP.TokenEmbedding加载预训练模型时,没有从预训练词表中找到这个词的处理方式。
:param word: 要添加进字典的新词, word为一个字符串
:param no_create_entry: 如果词语来自于非训练集建议设置为True。
如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独 如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独
的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新 的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新
加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这 加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这
个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的, 个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的,
则这个词将认为是需要创建单独的vector的。 则这个词将认为是需要创建单独的vector的。

""" """
self._add_no_create_entry(word, no_create_entry) self._add_no_create_entry(word, no_create_entry)
self.word_count[word] += 1 self.word_count[word] += 1
return self return self
def _add_no_create_entry(self, word, no_create_entry):
def _add_no_create_entry(self, word:Union[str, List[str]], no_create_entry:bool):
r""" r"""
在新加入word时,检查_no_create_word的设置。 在新加入word时,检查_no_create_word的设置。


:param str List[str] word:
:param bool no_create_entry:
:param word: 要添加的新词或者是List类型的新词,如word='I'或者word=['I', 'am', 'a', 'Chinese']均可
:param no_create_entry: 如果词语来自于非训练集建议设置为True。如果为True,则不会有这个词语创建一个单独的entry,
它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独的entry
:return: :return:

""" """
if isinstance(word, str) or not _is_iterable(word): if isinstance(word, str) or not _is_iterable(word):
word = [word] word = [word]
@@ -170,32 +188,32 @@ class Vocabulary(object):
self._no_create_word.pop(w) self._no_create_word.pop(w)
@_check_build_status @_check_build_status
def add_word(self, word, no_create_entry=False):
def add_word(self, word:str, no_create_entry:bool=False):
r""" r"""
增加一个新词在词典中的出现频率 增加一个新词在词典中的出现频率


:param str word: 新词
:param bool no_create_entry: 如果词语来自于非训练集建议设置为True。在使用fastNLP.TokenEmbedding加载预训练模型时,没有从预训练词表中找到这个词的处理方式。
如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独
的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新
加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这
个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的,
则这个词将认为是需要创建单独的vector的。
:param word: 要添加进字典的新词, word为一个字符串
:param no_create_entry: 如果词语来自于非训练集建议设置为True。如果为True,则不会有这个词语创建一个单独的entry,
它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独的entry。如果这个word来自于dev或者test,一般设置为True,
如果来自与train一般设置为False。以下两种情况: 如果新加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary
中且并不是no_create_entry的,则还是会为这词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary
中且并不是no_create_entry的,则这个词将认为是需要创建单独的vector的。
""" """
self.add(word, no_create_entry=no_create_entry) self.add(word, no_create_entry=no_create_entry)
@_check_build_status @_check_build_status
def add_word_lst(self, word_lst, no_create_entry=False):
def add_word_lst(self, word_lst: List[str], no_create_entry:bool=False):
r""" r"""
依次增加序列中词在词典中的出现频率 依次增加序列中词在词典中的出现频率


:param list[str] word_lst: 词的序列
:param bool no_create_entry: 如果词语来自于非训练集建议设置为True。在使用fastNLP.TokenEmbedding加载预训练模型时,没有从预训练词表中找到这个词的处理方式。
如果为True,则不会有这个词语创建一个单独的entry,它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独
的entry。如果这个word来自于dev或者test,一般设置为True,如果来自与train一般设置为False。以下两种情况: 如果新
加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary中且并不是no_create_entry的,则还是会为这
个词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary中且并不是no_create_entry的,
则这个词将认为是需要创建单独的vector的。
:param word_lst: 需要添加的新词的list序列,如word_lst=['I', 'am', 'a', 'Chinese']
:param no_create_entry: 如果词语来自于非训练集建议设置为True。如果为True,则不会有这个词语创建一个单独的entry,
它将一直被指向unk的表示; 如果为False,则为这个词创建一个单独的entry。如果这个word来自于dev或者test,一般设置为True,
如果来自与train一般设置为False。以下两种情况: 如果新加入一个word,且no_create_entry为True,但这个词之前已经在Vocabulary
中且并不是no_create_entry的,则还是会为这词创建一个单独的vector; 如果no_create_entry为False,但这个词之前已经在Vocabulary
中且并不是no_create_entry的,则这个词将认为是需要创建单独的vector的。
""" """
self.update(word_lst, no_create_entry=no_create_entry) self.update(word_lst, no_create_entry=no_create_entry)
return self return self
@@ -238,7 +256,7 @@ class Vocabulary(object):
return len(self._word2idx) return len(self._word2idx)
@_check_build_vocab @_check_build_vocab
def __contains__(self, item):
def __contains__(self, item:str):
r""" r"""
检查词是否被记录 检查词是否被记录


@@ -247,7 +265,7 @@ class Vocabulary(object):
""" """
return item in self._word2idx return item in self._word2idx
def has_word(self, w):
def has_word(self, w:str):
r""" r"""
检查词是否被记录:: 检查词是否被记录::


@@ -255,7 +273,7 @@ class Vocabulary(object):
# equals to # equals to
has_abc = 'abc' in vocab has_abc = 'abc' in vocab


:param item: the word
:param item: 输入的str类型的词
:return: ``True`` or ``False`` :return: ``True`` or ``False``
""" """
return self.__contains__(w) return self.__contains__(w)
@@ -263,7 +281,7 @@ class Vocabulary(object):
@_check_build_vocab @_check_build_vocab
def __getitem__(self, w): def __getitem__(self, w):
r""" r"""
To support usage like::
支持从字典中直接得到词语的index,例如::


vocab[w] vocab[w]
""" """
@@ -275,15 +293,15 @@ class Vocabulary(object):
raise ValueError("word `{}` not in vocabulary".format(w)) raise ValueError("word `{}` not in vocabulary".format(w))
@_check_build_vocab @_check_build_vocab
def index_dataset(self, *datasets, field_name, new_field_name=None):
def index_dataset(self, *datasets, field_name:Union[List, str], new_field_name:Union[List, str, None]=None):
r""" r"""
将DataSet中对应field的词转为数字,Example:: 将DataSet中对应field的词转为数字,Example::


# remember to use `field_name` # remember to use `field_name`
vocab.index_dataset(train_data, dev_data, test_data, field_name='words') vocab.index_dataset(train_data, dev_data, test_data, field_name='words')


:param ~fastNLP.DataSet,List[~fastNLP.DataSet] datasets: 需要转index的一个或多个数据集
:param list,str field_name: 需要转index的field, 若有多个 DataSet, 每个DataSet都必须有此 field.
:param datasets: 其类型为:~fastNLP.core.Dataset或者List[~fastNLP.core.Dataset] 需要转index的一个或多个数据集
:param field_name: 需要转index的field, 若有多个 DataSet, 每个DataSet都必须有此 field.
目前支持 ``str`` , ``List[str]`` 目前支持 ``str`` , ``List[str]``
:param list,str new_field_name: 保存结果的field_name. 若为 ``None`` , 将覆盖原field. :param list,str new_field_name: 保存结果的field_name. 若为 ``None`` , 将覆盖原field.
Default: ``None``. Default: ``None``.
@@ -333,17 +351,16 @@ class Vocabulary(object):
def _no_create_word_length(self): def _no_create_word_length(self):
return len(self._no_create_word) return len(self._no_create_word)
def from_dataset(self, *datasets, field_name, no_create_entry_dataset=None):
def from_dataset(self, *datasets, field_name:Union[str,List[str]], no_create_entry_dataset=None):
r""" r"""
使用dataset的对应field中词构建词典:: 使用dataset的对应field中词构建词典::


# remember to use `field_name` # remember to use `field_name`
vocab.from_dataset(train_data1, train_data2, field_name='words')
vocab.from_dataset(train_data1, train_data2, field_name='words', no_create_entry_dataset=[test_data1, test_data2])


:param ~fastNLP.DataSet,List[~fastNLP.DataSet] datasets: 需要转index的一个或多个数据集
:param str,List[str] field_name: 可为 ``str`` 或 ``List[str]`` .
构建词典所使用的 field(s), 支持一个或多个field,若有多个 DataSet, 每个DataSet都必须有这些field. 目前支持的field结构
: ``str`` , ``List[str]``
:param 其类型为:~fastNLP.core.Dataset或者List[~fastNLP.core.Dataset] 需要转index的一个或多个数据集
:param field_name: 构建词典所使用的 field(s), 支持一个或多个field,若有多个 DataSet, 每个DataSet都必须有这些field.
目前支持的field结构: ``str`` , ``List[str]``
:param no_create_entry_dataset: 可以传入DataSet, List[DataSet]或者None(默认), 建议直接将非训练数据都传入到这个参数。该选项用在接下来的模型会使用pretrain :param no_create_entry_dataset: 可以传入DataSet, List[DataSet]或者None(默认), 建议直接将非训练数据都传入到这个参数。该选项用在接下来的模型会使用pretrain
的embedding(包括glove, word2vec, elmo与bert)且会finetune的情况。如果仅使用来自于train的数据建立vocabulary,会导致test与dev 的embedding(包括glove, word2vec, elmo与bert)且会finetune的情况。如果仅使用来自于train的数据建立vocabulary,会导致test与dev
中的数据无法充分利用到来自于预训练embedding的信息,所以在建立词表的时候将test与dev考虑进来会使得最终的结果更好。 中的数据无法充分利用到来自于预训练embedding的信息,所以在建立词表的时候将test与dev考虑进来会使得最终的结果更好。
@@ -351,7 +368,8 @@ class Vocabulary(object):
finetune embedding的话,这个词在更新之后可能会有更好的表示; 而如果这个词仅出现在了dev或test中,那么就不能为它们单独建立vector, finetune embedding的话,这个词在更新之后可能会有更好的表示; 而如果这个词仅出现在了dev或test中,那么就不能为它们单独建立vector,
而应该让它指向unk这个vector的值。所以只位于no_create_entry_dataset中的token,将首先从预训练的词表中寻找它的表示, 而应该让它指向unk这个vector的值。所以只位于no_create_entry_dataset中的token,将首先从预训练的词表中寻找它的表示,
如果找到了,就使用该表示; 如果没有找到,则认为该词的表示应该为unk的表示。 如果找到了,就使用该表示; 如果没有找到,则认为该词的表示应该为unk的表示。
:return self:
:return Vocabulary自身

""" """
if isinstance(field_name, str): if isinstance(field_name, str):
field_name = [field_name] field_name = [field_name]
@@ -395,15 +413,16 @@ class Vocabulary(object):
dataset.apply(partial_construct_vocab) dataset.apply(partial_construct_vocab)
return self return self
def _is_word_no_create_entry(self, word):
def _is_word_no_create_entry(self, word:str):
r""" r"""
判断当前的word是否是不需要创建entry的,具体参见from_dataset的说明 判断当前的word是否是不需要创建entry的,具体参见from_dataset的说明
:param word: str
:return: bool

:param word: 输入的str类型的词语
:return: bool值的判断结果
""" """
return word in self._no_create_word return word in self._no_create_word
def to_index(self, w):
def to_index(self, w:str):
r""" r"""
将词转为数字. 若词不再词典中被记录, 将视为 unknown, 若 ``unknown=None`` , 将抛出 ``ValueError`` :: 将词转为数字. 若词不再词典中被记录, 将视为 unknown, 若 ``unknown=None`` , 将抛出 ``ValueError`` ::


@@ -411,8 +430,8 @@ class Vocabulary(object):
# equals to # equals to
index = vocab['abc'] index = vocab['abc']


:param str w: a word
:return int index: the number
:param w: 需要输入的词语
:return 词语w对应的int类型的index
""" """
return self.__getitem__(w) return self.__getitem__(w)
@@ -420,7 +439,7 @@ class Vocabulary(object):
@_check_build_vocab @_check_build_vocab
def unknown_idx(self): def unknown_idx(self):
r""" r"""
unknown 对应的数字.
获得unknown 对应的数字.
""" """
if self.unknown is None: if self.unknown is None:
return None return None
@@ -430,14 +449,14 @@ class Vocabulary(object):
@_check_build_vocab @_check_build_vocab
def padding_idx(self): def padding_idx(self):
r""" r"""
padding 对应的数字
获得padding 对应的数字
""" """
if self.padding is None: if self.padding is None:
return None return None
return self._word2idx[self.padding] return self._word2idx[self.padding]
@_check_build_vocab @_check_build_vocab
def to_word(self, idx):
def to_word(self, idx: int):
r""" r"""
给定一个数字, 将其转为对应的词. 给定一个数字, 将其转为对应的词.


@@ -460,7 +479,8 @@ class Vocabulary(object):
return self return self
def __getstate__(self): def __getstate__(self):
r"""Use to prepare data for pickle.
r"""
用来从pickle中加载data


""" """
len(self) # make sure vocab has been built len(self) # make sure vocab has been built
@@ -470,7 +490,8 @@ class Vocabulary(object):
return state return state
def __setstate__(self, state): def __setstate__(self, state):
r"""Use to restore state from pickle.
r"""
支持pickle的保存,保存到pickle的data state


""" """
self.__dict__.update(state) self.__dict__.update(state)
@@ -485,11 +506,11 @@ class Vocabulary(object):
for index in range(len(self._word2idx)): for index in range(len(self._word2idx)):
yield self.to_word(index), index yield self.to_word(index), index


def save(self, filepath):
def save(self, filepath: [str, io.StringIO]):
r""" r"""

:param str,io.StringIO filepath: Vocabulary的储存路径
:param filepath: Vocabulary的储存路径
:return: :return:

""" """
if isinstance(filepath, io.IOBase): if isinstance(filepath, io.IOBase):
assert filepath.writable() assert filepath.writable()
@@ -521,10 +542,11 @@ class Vocabulary(object):
f.close() f.close()


@staticmethod @staticmethod
def load(filepath):
def load(filepath: Union[str,io.StringIO]):
r""" r"""
从文件路径中加载数据


:param str,io.StringIO filepath: Vocabulary的读取路径
:param filepath: Vocabulary的读取路径
:return: Vocabulary :return: Vocabulary
""" """
if isinstance(filepath, io.IOBase): if isinstance(filepath, io.IOBase):


+ 0
- 0
pad_val View File


Loading…
Cancel
Save