You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

tutorial_1_data_preprocess.rst 6.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. ==============================
  2. 使用DataSet预处理文本
  3. ==============================
  4. :class:`~fastNLP.DataSet` 是fastNLP中用于承载数据的容器。可以将DataSet看做是一个表格,
  5. 每一行是一个sample (在fastNLP中被称为 :mod:`~fastNLP.core.instance` ),
  6. 每一列是一个feature (在fastNLP中称为 :mod:`~fastNLP.core.field` )。
  7. .. csv-table::
  8. :header: "sentence", "words", "seq_len"
  9. "This is the first instance .", "[This, is, the, first, instance, .]", 6
  10. "Second instance .", "[Second, instance, .]", 3
  11. "Third instance .", "[Third, instance, .]", 3
  12. "...", "[...]", "..."
  13. 上面是一个样例数据中 DataSet 的存储结构。其中它的每一行是一个 :class:`~fastNLP.Instance` 对象; 每一列是一个 :class:`~fastNLP.FieldArray` 对象。
  14. -----------------------------
  15. 数据集构建和删除
  16. -----------------------------
  17. 我们使用传入字典的方式构建一个数据集,这是 :class:`~fastNLP.DataSet` 初始化的最基础的方式
  18. .. code-block:: python
  19. from fastNLP import DataSet
  20. data = {'sentence':["This is the first instance .", "Second instance .", "Third instance ."],
  21. 'words': [['this', 'is', 'the', 'first', 'instance', '.'], ['Second', 'instance', '.'], ['Third', 'instance', '.']],
  22. 'seq_len': [6, 3, 3]}
  23. dataset = DataSet(data)
  24. # 传入的dict的每个key的value应该为具有相同长度的list
  25. 我们还可以使用 :func:`~fastNLP.DataSet.append` 方法向数据集内增加数据
  26. .. code-block:: python
  27. from fastNLP import DataSet
  28. from fastNLP import Instance
  29. dataset = DataSet()
  30. instance = Instance(sentence="This is the first instance",
  31. words=['this', 'is', 'the', 'first', 'instance', '.'],
  32. seq_len=6)
  33. dataset.append(instance)
  34. # 可以继续append更多内容,但是append的instance应该和前面的instance拥有完全相同的field
  35. 另外,我们还可以用 :class:`~fastNLP.Instance` 数组的方式构建数据集
  36. .. code-block:: python
  37. from fastNLP import DataSet
  38. from fastNLP import Instance
  39. dataset = DataSet([
  40. Instance(sentence="This is the first instance",
  41. words=['this', 'is', 'the', 'first', 'instance', '.'],
  42. seq_len=6),
  43. Instance(sentence="Second instance .",
  44. words=['Second', 'instance', '.'],
  45. seq_len=3)
  46. ])
  47. 在初步构建完数据集之后,我们可以通过 `for` 循环遍历 :class:`~fastNLP.DataSet` 中的内容。
  48. .. code-block:: python
  49. for instance in dataset:
  50. # do something
  51. FastNLP 同样提供了多种删除数据的方法 :func:`~fastNLP.DataSet.drop` 、 :func:`~fastNLP.DataSet.delete_instance` 和 :func:`~fastNLP.DataSet.delete_field`
  52. .. code-block:: python
  53. from fastNLP import DataSet
  54. dataset = DataSet({'a': list(range(-5, 5))})
  55. # 返回满足条件的instance,并放入DataSet中
  56. dropped_dataset = dataset.drop(lambda ins:ins['a']<0, inplace=False)
  57. # 在dataset中删除满足条件的instance
  58. dataset.drop(lambda ins:ins['a']<0) # dataset的instance数量减少
  59. # 删除第3个instance
  60. dataset.delete_instance(2)
  61. # 删除名为'a'的field
  62. dataset.delete_field('a')
  63. -----------------------------
  64. 简单的数据预处理
  65. -----------------------------
  66. 因为 fastNLP 中的数据是按列存储的,所以大部分的数据预处理操作是以列( :mod:`~fastNLP.core.field` )为操作对象的。
  67. 首先,我们可以检查特定名称的 :mod:`~fastNLP.core.field` 是否存在,并对其进行改名。
  68. .. code-block:: python
  69. # 检查是否存在名为'a'的field
  70. dataset.has_field('a') # 或 ('a' in dataset)
  71. # 将名为'a'的field改名为'b'
  72. dataset.rename_field('a', 'b')
  73. # DataSet的长度
  74. len(dataset)
  75. 其次,我们可以使用 :func:`~fastNLP.DataSet.apply` 或 :func:`~fastNLP.DataSet.apply_field` 进行数据预处理操作操作。
  76. 这两个方法通过传入一个对单一 :mod:`~fastNLP.core.instance` 操作的函数,
  77. 自动地帮助你对一个 :mod:`~fastNLP.core.field` 中的每个 :mod:`~fastNLP.core.instance` 调用这个函数,完成整体的操作。
  78. 这个传入的函数可以是 lambda 匿名函数,也可以是完整定义的函数。同时,你还可以用 ``new_field_name`` 参数指定数据处理后存储的 :mod:`~fastNLP.core.field` 的名称。
  79. .. code-block:: python
  80. from fastNLP import DataSet
  81. data = {'sentence':["This is the first instance .", "Second instance .", "Third instance ."]}
  82. dataset = DataSet(data)
  83. # 将句子分成单词形式, 详见DataSet.apply()方法
  84. dataset.apply(lambda ins: ins['sentence'].split(), new_field_name='words')
  85. # 或使用DataSet.apply_field()
  86. dataset.apply_field(lambda sent:sent.split(), field_name='sentence', new_field_name='words')
  87. # 除了匿名函数,也可以定义函数传递进去
  88. def get_words(instance):
  89. sentence = instance['sentence']
  90. words = sentence.split()
  91. return words
  92. dataset.apply(get_words, new_field_name='words')
  93. 除了手动处理数据集之外,你还可以使用 fastNLP 提供的各种 :class:`~fastNLP.io.base_loader.DataSetLoader` 来进行数据处理。
  94. 详细请参考这篇教程 :doc:`使用DataSetLoader加载数据集 </tutorials/tutorial_2_load_dataset>` 。
  95. -----------------------------
  96. DataSet与pad
  97. -----------------------------
  98. 在fastNLP里,pad是与一个 :mod:`~fastNLP.core.field` 绑定的。即不同的 :mod:`~fastNLP.core.field` 可以使用不同的pad方式,比如在英文任务中word需要的pad和
  99. character的pad方式往往是不同的。fastNLP是通过一个叫做 :class:`~fastNLP.Padder` 的子类来完成的。
  100. 默认情况下,所有field使用 :class:`~fastNLP.AutoPadder`
  101. 。可以通过使用以下方式设置Padder(如果将padder设置为None,则该field不会进行pad操作)。
  102. 大多数情况下直接使用 :class:`~fastNLP.AutoPadder` 就可以了。
  103. 如果 :class:`~fastNLP.AutoPadder` 或 :class:`~fastNLP.EngChar2DPadder` 无法满足需求,
  104. 也可以自己写一个 :class:`~fastNLP.Padder` 。
  105. .. code-block:: python
  106. from fastNLP import DataSet
  107. from fastNLP import EngChar2DPadder
  108. import random
  109. dataset = DataSet()
  110. max_chars, max_words, sent_num = 5, 10, 20
  111. contents = [[
  112. [random.randint(1, 27) for _ in range(random.randint(1, max_chars))]
  113. for _ in range(random.randint(1, max_words))
  114. ] for _ in range(sent_num)]
  115. # 初始化时传入
  116. dataset.add_field('chars', contents, padder=EngChar2DPadder())
  117. # 直接设置
  118. dataset.set_padder('chars', EngChar2DPadder())
  119. # 也可以设置pad的value
  120. dataset.set_pad_val('chars', -1)