fastNLP.core.dataset¶
DataSet
是fastNLP中用于承载数据的容器。可以将DataSet看做是一个表格,
每一行是一个sample (在fastNLP中被称为 instance
),
每一列是一个feature (在fastNLP中称为 field
)。
sentence | words | seq_len |
---|---|---|
This is the first instance . | [This, is, the, first, instance, .] | 6 |
Second instance . | [Second, instance, .] | 3 |
Third instance . | [Third, instance, .] | 3 |
... | [...] | ... |
在fastNLP内部每一行是一个 Instance
对象; 每一列是一个 FieldArray
对象。
2.DataSet与预处理¶
常见的预处理有如下几种
2.1 从某个文本文件读取内容¶
注解
直接读取特定数据集的数据请参考 使用Loader和Pipe加载并处理数据集
2.2 对DataSet中的内容处理¶
2.3 删除DataSet的内容¶
2.4 遍历DataSet的内容¶
2.5 一些其它操作¶
3.DataSet与自然语言处理(NLP)¶
在目前深度学习的模型中,大都依赖于随机梯度下降法(SGD)进行模型的优化。随机梯度下降需要将数据切分成一个个的 batch, 一个batch进行一次前向计算(forward)与梯度后向传播(backward)。在自然语言处理的场景下,往往还需要对数据进行pad。这是 由于句子的长度一般是不同的,但是一次batch中的每个field都必须是一个tensor,所以需要将所有句子都补齐到相同的长度。
3.1 DataSet与DataSetIter¶
我们先看fastNLP中如何将数据分成一个一个的batch的例子, 这里我们使用随机生成的数据来模拟一个二分类文本分类任务, words和characters是输入,labels是文本类别
其中
DataSetIter
是用于从DataSet中按照batch_size为大小取出batch的迭代器,SequentialSampler
用于指示DataSetIter
以怎样的 顺序从DataSet中取出instance以组成一个batch, 更详细的说明请参照DataSetIter
和SequentialSampler
文档。通过
DataSet.set_input('words', 'chars')
, fastNLP将认为 words 和 chars 这两个field都是input,并将它们都放入迭代器 生成的第一个dict中;DataSet.set_target('labels')
, fastNLP将认为 labels 这个field是target,并将其放入到迭代器的第 二个dict中。如上例中所打印结果。分为input和target的原因是由于它们在被Trainer
所使用时会有所差异, 详见Trainer
当把某个field设置为 target 或者 input 的时候(两者不是互斥的,可以同时设为两种),fastNLP不仅仅只是将其放 置到不同的dict中,而还会对被设置为 input 或 target 的 field 进行类型检查。类型检查的目的是为了看能否把该 field 转为 pytorch的
torch.LongTensor
或torch.FloatTensor
类型 (也可以在DataSetIter
中设置输出numpy类型,参考DataSetIter
)。如上例所示,fastNLP已将 words ,chars 和 label 转为了
Tensor
类型。 如果 field 在每个 instance 都拥有相同的维度(不能超过两维),且最内层的元素都为相同的 type(int, float, np.int*, np.float*), 则fastNLP默认将对该 field 进行pad。也支持全为str的field作为target和input,这种情况下,fastNLP默认不进行pad。 另外,当某个 field 已经被设置为了 target 或者 input 后,之后 append 的 instance 对应的 field 必须要和前面已有的内容一致,否则会报错。可以查看field的dtype:
from fastNLP import DataSet d = DataSet({'a': [0, 1, 3], 'b':[[1.0, 2.0], [0.1, 0.2], [3]]}) d.set_input('a', 'b') d.a.dtype >> numpy.int64 d.b.dtype >> numpy.float64 # 默认情况下'a'这个field将被转换为torch.LongTensor,但如果需要其为torch.FloatTensor可以手动修改dtype d.a.dtype = float # 请确保该field的确可以全部转换为float。如果某个field中出现了多种类型混合(比如一部分为str,一部分为int)的情况,fastNLP无法判断该field的类型,会报如下的 错误:
from fastNLP import DataSet d = DataSet({'data': [1, 'a']}) d.set_input('data') >> RuntimeError: Mixed data types in Field data: [<class 'str'>, <class 'int'>]可以通过设置以忽略对该field进行类型检查:
from fastNLP import DataSet d = DataSet({'data': [1, 'a']}) d.set_ignore_type('data') d.set_input('data')当某个field被设置为忽略type之后,fastNLP将不对其进行pad。
3.2 DataSet与pad¶
在fastNLP里,pad是与一个field绑定的。即不同的field可以使用不同的pad方式,比如在英文任务中word需要的pad和 character的pad方式往往是不同的。fastNLP是通过一个叫做Padder
的子类来完成的。 默认情况下,所有field使用AutoPadder
。可以通过使用以下方式设置Padder(如果将padder设置为None,则该field不会进行pad操作)。 大多数情况下直接使用AutoPadder
就可以了。 如果AutoPadder
或EngChar2DPadder
无法满足需求, 也可以自己写一个Padder
。
3.3 根据DataSet中多个field合成新的field¶
DataSet支持在进行batch时,默认只能看到当前的field的值,但在某些训练中可能存在以下的情况: (1)需要两个field拼接成为一个field; (2)需要在batch中进行负采样。这时候就需要能够同时利用多个field进行batch的操作,DataSet中的add_collate_fn()函数支持添加 自定义涉及多个field的collate_fn函数。例如下例中将两个field拼接成一个field的场景
-
class
fastNLP.core.dataset.
DataSet
(data=None)[源代码]¶ 别名
fastNLP.DataSet
fastNLP.core.dataset.DataSet
fastNLP的数据容器,详细的使用方法见文档
fastNLP.core.dataset
-
__init__
(data=None)[源代码]¶ 参数: data -- 如果为dict类型,则每个key的value应该为等长的list; 如果为list, 每个元素应该为具有相同field的 Instance
。
-
add_collate_fn
(fn, name=None)[源代码]¶ 添加 CollateFn,collate_fn允许在生成的batch的过程中动态生成一些数据(在DataSetIter作为迭代器的情况下有效,默认情况下就是用的 这个)。支持依次添加多个collate_fn, 如果相同的key,后面的collate_fn的结果覆盖前面的collate_fn的结果。
参数: - fn (callable) -- 传入一个可调用的function, 该function可接受的参数为List[(ind1, instance1), (ind2, instance2)] (某个batch被选中的所有的indice以及instance),其中ind1/ind2是该instance在dataset中的index,instance1/instance2是 这次batch取出来的数据,包含了所有的field。返回值需要为两个dict,第一个dict的值将被认为是input,第二个dict的值被认为是 target,返回的值至多允许一个空dict。若返回的dict中包含了被设置为input或target的field的名称,将覆盖dataset中的field。 fastNLP不会将collate_fn的返回结果pad和转换为tensor,需要在collate_fn中完成pad和转换为tensor(不需要将tensor移动到 gpu中,fastNLP会自动将其移动到特定gpu)。不要修改传入collate_fn中的数据,否则可能导致未知问题。
- name (str,int) -- collate_fn的名称,如果不传入,默认使用自增长的数字作为key。相同的name会覆盖之前的collate_fn。
-
add_field
(field_name, fields, padder=<fastNLP.core.field.AutoPadder object>, is_input=False, is_target=False, ignore_type=False)[源代码]¶ 新增一个field
参数: - field_name (str) -- 新增的field的名称
- fields (list) -- 需要新增的field的内容
- padder (None,Padder) -- 如果为None,则不进行pad,默认使用
AutoPadder
自动判断是否需要做pad。 - is_input (bool) -- 新加入的field是否是input
- is_target (bool) -- 新加入的field是否是target
- ignore_type (bool) -- 是否忽略对新加入的field的类型检查
-
add_fieldarray
(field_name, fieldarray)[源代码]¶ 将fieldarray添加到DataSet中.
参数: - field_name (str) -- 新加入的field的名称
- fieldarray (FieldArray) -- 需要加入DataSet的field的内容
返回:
-
add_seq_len
(field_name: str, new_field_name='seq_len')[源代码]¶ 将使用len()直接对field_name中每个元素作用,将其结果作为sequence length, 并放入seq_len这个field。
参数: - field_name -- str.
- new_field_name -- str. 新的field_name
返回:
-
append
(instance)[源代码]¶ 将一个instance对象append到DataSet后面。
参数: instance (Instance) -- 若DataSet不为空,则instance应该拥有和DataSet完全一样的field。
-
apply
(func, new_field_name=None, **kwargs)[源代码]¶ 将DataSet中每个instance传入到func中,并获取它的返回值.
参数: - func (callable) -- 参数是
DataSet
中的Instance
- new_field_name (None,str) -- 将func返回的内容放入到 new_field_name 这个field中,如果名称与已有的field相同,则覆 盖之前的field。如果为None则不创建新的field。
- kwargs (optional) --
支持输入is_input,is_target,ignore_type
- is_input: bool, 如果为True则将 new_field_name 的field设置为input
- is_target: bool, 如果为True则将 new_field_name 的field设置为target
- ignore_type: bool, 如果为True则将 new_field_name 的field的ignore_type设置为true, 忽略其类型
Return List[Any]: 里面的元素为func的返回值,所以list长度为DataSet的长度
- func (callable) -- 参数是
-
apply_field
(func, field_name, new_field_name=None, **kwargs)[源代码]¶ 将DataSet中的每个instance中的名为 field_name 的field传给func,并获取它的返回值。
参数: - func (callable) -- input是instance中名为 field_name 的field的内容。
- field_name (str) -- 传入func的是哪个field。
- new_field_name (None,str) -- 将func返回的内容放入到 new_field_name 这个field中,如果名称与已有的field相同,则覆 盖之前的field。如果为None则不创建新的field。
- kwargs (optional) --
支持输入is_input,is_target,ignore_type
- is_input: bool, 如果为True则将名为 new_field_name 的field设置为input
- is_target: bool, 如果为True则将名为 new_field_name 的field设置为target
- ignore_type: bool, 如果为True则将名为 new_field_name 的field的ignore_type设置为true, 忽略其类型
Return List[Any]: 里面的元素为func的返回值,所以list长度为DataSet的长度
-
apply_field_more
(func, field_name, modify_fields=True, **kwargs)[源代码]¶ 将
DataSet
中的每个Instance
中的名为 field_name 的field 传给 func,并获取它的返回值。 func 可以返回一个或多个 field 上的结果。注解
apply_field_more
与apply_field
的区别参考apply_more()
中关于apply_more
与apply
区别的介绍。参数: - func (callable) -- 参数是
DataSet
中的Instance
,返回值是一个字典,key 是field 的名字,value 是对应的结果 - field_name (str) -- 传入func的是哪个field。
- modify_fields (bool) -- 是否用结果修改 DataSet 中的 Field, 默认为 True
- kwargs (optional) --
支持输入is_input,is_target,ignore_type
- is_input: bool, 如果为True则将被修改的field设置为input
- is_target: bool, 如果为True则将被修改的field设置为target
- ignore_type: bool, 如果为True则将被修改的field的ignore_type设置为true, 忽略其类型
:return Dict[int:Field]: 返回一个字典
- func (callable) -- 参数是
-
apply_more
(func, modify_fields=True, **kwargs)[源代码]¶ 将
DataSet
中每个Instance
传入到func中,并获取它的返回值。func可以返回一个或多个 field 上的结果。注解
apply_more
与apply
的区别:apply_more
可以返回多个 field 的结果,apply
只可以返回一个field 的结果;apply_more
的返回值是一个字典,每个 key-value 对中的 key 表示 field 的名字,value 表示计算结果;apply_more
默认修改DataSet
中的 field ,apply
默认不修改。
参数: - func (callable) -- 参数是
DataSet
中的Instance
,返回值是一个字典,key 是field 的名字,value 是对应的结果 - modify_fields (bool) -- 是否用结果修改
DataSet
中的Field
, 默认为 True - kwargs (optional) --
支持输入is_input,is_target,ignore_type
- is_input: bool, 如果为True则将被修改的的field设置为input
- is_target: bool, 如果为True则将被修改的的field设置为target
- ignore_type: bool, 如果为True则将被修改的的field的ignore_type设置为true, 忽略其类型
:return Dict[int:Field]: 返回一个字典
-
copy_field
(field_name, new_field_name)[源代码]¶ 深度copy名为field_name的field到new_field_name
参数: - field_name (str) -- 需要copy的field。
- new_field_name (str) -- copy生成的field名称
返回: self
-
delete_collate_fn
(name=None)[源代码]¶ 删除某个collate_fn
参数: name (str,int) -- 如果为None,则删除最近加入的collate_fn 返回:
-
drop
(func, inplace=True)[源代码]¶ func接受一个Instance,返回bool值。返回值为True时,该Instance会被移除或者不会包含在返回的DataSet中。
参数: - func (callable) -- 接受一个Instance作为参数,返回bool值。为True时删除该instance
- inplace (bool) -- 是否在当前DataSet中直接删除instance;如果为False,将返回一个新的DataSet。
返回: DataSet
-
has_field
(field_name)[源代码]¶ 判断DataSet中是否有名为field_name这个field
参数: field_name (str) -- field的名称 Return bool: 表示是否有名为field_name这个field
-
static
load
(path)[源代码]¶ 从保存的DataSet pickle文件的路径中读取DataSet
参数: path (str) -- 从哪里读取DataSet 返回: 读取后的 读取后的DataSet
。
-
print_field_meta
()[源代码]¶ 输出当前field的meta信息, 形似下列的输出:
+-------------+-------+-------+ | field_names | x | y | +=============+=======+=======+ | is_input | True | False | | is_target | False | False | | ignore_type | False | | | pad_value | 0 | | +-------------+-------+-------+
参数: - field_names -- DataSet中field的名称
- is_input -- field是否为input
- is_target -- field是否为target
- ignore_type -- 是否忽略该field的type, 一般仅在该field至少为input或target时才有意义
- pad_value -- 该field的pad的值,仅在该field为input或target时有意义
返回:
-
rename_field
(field_name, new_field_name)[源代码]¶ 将某个field重新命名.
参数: - field_name (str) -- 原来的field名称。
- new_field_name (str) -- 修改为new_name。
-
set_ignore_type
(*field_names, flag=True)[源代码]¶ 将field设置为忽略类型状态。当某个field被设置了ignore_type, 则在被设置为target或者input时将不进行类型检查, 默认情况下也不进行pad。如果仍需要pad该field,可通过自定义Padder实现,若该field需要转换为tensor,需要在padder 中转换,但不需要在padder中移动到gpu。
参数: - field_names (str) -- field的名称
- flag (bool) -- 将field_name的ignore_type状态设置为flag
返回:
-
set_input
(*field_names, flag=True, use_1st_ins_infer_dim_type=True)[源代码]¶ 将field_names的field设置为input:
dataset.set_input('words', 'seq_len') # 将words和seq_len这两个field的input属性设置为True dataset.set_input('words', flag=False) # 将words这个field的input属性设置为False
参数: - field_names (str) -- field的名称
- flag (bool) -- 将field_name的input状态设置为flag
- use_1st_ins_infer_dim_type (bool) -- 如果为True,将不会check该列是否所有数据都是同样的维度,同样的类型。将直接使用第一 行的数据进行类型和维度推断本列的数据的类型和维度。
-
set_pad_val
(field_name, pad_val)[源代码]¶ 为某个field设置对应的pad_val.
参数: - field_name (str) -- 修改该field的pad_val
- pad_val (int) -- 该field的padder会以pad_val作为padding index
-
set_padder
(field_name, padder)[源代码]¶ 为field_name设置padder:
from fastNLP import EngChar2DPadder padder = EngChar2DPadder() dataset.set_padder('chars', padder) # 则chars这个field会使用EngChar2DPadder进行pad操作
参数: - field_name (str) -- 设置field的padding方式为padder
- padder (None,Padder) -- 设置为None即删除padder, 即对该field不进行pad操作。
-
set_target
(*field_names, flag=True, use_1st_ins_infer_dim_type=True)[源代码]¶ 将field_names的field设置为target
Example:
dataset.set_target('labels', 'seq_len') # 将labels和seq_len这两个field的target属性设置为True dataset.set_target('labels', 'seq_lens', flag=False) # 将labels和seq_len的target属性设置为False
参数: - field_names (str) -- field的名称
- flag (bool) -- 将field_name的target状态设置为flag
- use_1st_ins_infer_dim_type (bool) -- 如果为True,将不会check该列是否所有数据都是同样的维度,同样的类型。将直接使用第一 行的数据进行类型和维度推断本列的数据的类型和维度。
-