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 8.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. ==============================
  2. fastNLP中的DataSet
  3. ==============================
  4. :class:`~fastNLP.DataSet` 是fastNLP用于承载数据的类,一般训练集、验证集和测试集会被加载为三个单独的 :class:`~fastNLP.DataSet` 对象。
  5. :class:`~fastNLP.DataSet` 中的数据组织形式类似一个表格,比如下面 :class:`~fastNLP.DataSet` 一共有3列,列在fastNLP中被称为field。
  6. .. csv-table::
  7. :header: "raw_chars", "chars", "seq_len"
  8. "历任公司副总经理、总工程师,", "[历 任 公 司 副 总 经 理 、 总 工 程 师 ,]", 6
  9. "Third instance .", "[Third, instance, .]", 3
  10. "...", "[...]", "..."
  11. 每一行是一个instance (在fastNLP中被称为 :mod:`~fastNLP.core.Instance` ),
  12. 每一列是一个field (在fastNLP中称为 :mod:`~fastNLP.core.FieldArray` )。
  13. DataSet的构建
  14. -----------------------------
  15. 我们使用传入字典的方式初始化一个DataSet,这是 :class:`~fastNLP.DataSet` 初始化的最基础的方式
  16. .. code-block:: python
  17. from fastNLP import DataSet
  18. data = {'raw_words':["This is the first instance .", "Second instance .", "Third instance ."],
  19. 'words': [['this', 'is', 'the', 'first', 'instance', '.'], ['Second', 'instance', '.'], ['Third', 'instance', '.']],
  20. 'seq_len': [6, 3, 3]}
  21. dataset = DataSet(data)
  22. # 传入的dict的每个key的value应该为具有相同长度的list
  23. print(dataset)
  24. 输出为::
  25. +------------------------------+------------------------------------------------+---------+
  26. | raw_words | words | seq_len |
  27. +------------------------------+------------------------------------------------+---------+
  28. | This is the first instance . | ['this', 'is', 'the', 'first', 'instance', ... | 6 |
  29. | Second instance . | ['Second', 'instance', '.'] | 3 |
  30. | Third instance . | ['Third', 'instance', '.'] | 3 |
  31. +------------------------------+------------------------------------------------+---------+
  32. 我们还可以使用 :func:`~fastNLP.DataSet.append` 方法向DataSet增加数据
  33. .. code-block:: python
  34. from fastNLP import DataSet
  35. from fastNLP import Instance
  36. dataset = DataSet()
  37. instance = Instance(raw_words="This is the first instance",
  38. words=['this', 'is', 'the', 'first', 'instance', '.'],
  39. seq_len=6)
  40. dataset.append(instance)
  41. # 可以继续append更多内容,但是append的instance应该和前面的instance拥有完全相同的field
  42. 另外,我们还可以用 :class:`~fastNLP.Instance` 数组的方式构建DataSet
  43. .. code-block:: python
  44. from fastNLP import DataSet
  45. from fastNLP import Instance
  46. dataset = DataSet([
  47. Instance(raw_words="This is the first instance",
  48. words=['this', 'is', 'the', 'first', 'instance', '.'],
  49. seq_len=6),
  50. Instance(raw_words="Second instance .",
  51. words=['Second', 'instance', '.'],
  52. seq_len=3)
  53. ])
  54. 在初步构建完DataSet之后,我们可以通过 `for` 循环遍历 :class:`~fastNLP.DataSet` 中的内容。
  55. .. code-block:: python
  56. for instance in dataset:
  57. # do something
  58. DataSet的删除
  59. -----------------------------
  60. FastNLP 同样提供了多种删除数据的方法 :func:`~fastNLP.DataSet.drop` 、 :func:`~fastNLP.DataSet.delete_instance` 和 :func:`~fastNLP.DataSet.delete_field`
  61. 我们先用下面的代码生成一个只有两列的样例DataSet,第一列的值分别为 -5 ~ 4,第二列的值均为 0.
  62. .. code-block:: python
  63. from fastNLP import DataSet
  64. dataset = DataSet({'a': range(-5, 5), 'c': [0]*10})
  65. 然后我们使用三种方法进行删除,删除后的DataSet仅包含名为 c 的一列,包含4个值为0 的数据。
  66. .. code-block:: python
  67. # 不改变dataset,生成一个删除了满足条件的instance的新 DataSet
  68. dropped_dataset = dataset.drop(lambda ins:ins['a']<0, inplace=False)
  69. # 在dataset中删除满足条件的instance
  70. dataset.drop(lambda ins:ins['a']<0)
  71. # 删除第3个instance
  72. dataset.delete_instance(2)
  73. # 删除名为'a'的field
  74. dataset.delete_field('a')
  75. 简单的数据预处理
  76. -----------------------------
  77. 因为 fastNLP 中的数据是按列存储的,所以大部分的数据预处理操作是以列( :mod:`~fastNLP.core.field` )为操作对象的。
  78. 首先,我们可以检查特定名称的 :mod:`~fastNLP.core.field` 是否存在,并对其进行改名。
  79. .. code-block:: python
  80. # 检查是否存在名为'a'的field
  81. dataset.has_field('a') # 或 ('a' in dataset)
  82. # 将名为'c'的field改名为'b'
  83. dataset.rename_field('c', 'b')
  84. # DataSet的长度
  85. len(dataset)
  86. 其次,我们可以使用 :func:`~fastNLP.DataSet.apply` 或 :func:`~fastNLP.DataSet.apply_field` 进行数据预处理操作操作。
  87. 使用以上的两个方法需要传入一个函数,函数可以是 lambda 匿名函数,也可以是完整定义的函数,fastNLP将对DataSet遍历地应用该函数。
  88. 同时,你还可以用 ``new_field_name`` 参数指定函数返回值组成的新 :mod:`~fastNLP.core.field` 的名称。
  89. .. code-block:: python
  90. from fastNLP import DataSet
  91. data = {'raw_words':["This is the first instance .", "Second instance .", "Third instance ."]}
  92. dataset = DataSet(data)
  93. # 将句子分成单词形式, 详见DataSet.apply()方法
  94. dataset.apply(lambda ins: ins['raw_words'].split(), new_field_name='words')
  95. # 或使用DataSet.apply_field()
  96. dataset.apply_field(lambda sent:sent.split(), field_name='raw_words', new_field_name='words')
  97. # 除了匿名函数,也可以定义函数传递进去
  98. def get_words(instance):
  99. sentence = instance['raw_words']
  100. words = sentence.split()
  101. return words
  102. dataset.apply(get_words, new_field_name='words')
  103. 除了手动处理数据集之外,你还可以使用 fastNLP 提供的各种 :class:`~fastNLP.io.Loader` 和 :class:`~fastNLP.io.Pipe` 来进行数据处理。
  104. 详细请参考这篇教程 :doc:`使用Loader和Pipe处理数据 </tutorials/tutorial_4_load_dataset>` 。
  105. fastNLP中field的命名习惯
  106. -----------------------------
  107. 在英文任务中,fastNLP常用的field名称有:
  108. - **raw_words**: 表示的是原始的str。例如"This is a demo sentence ."。存在多个raw_words的情况,例如matching任务,它们会被定义为raw_words0, raw_words1。但在conll格式下,raw_words列也可能为["This", "is", "a", "demo", "sentence", "."]的形式。
  109. - **words**: 表示的是已经tokenize后的词语。例如["This", "is", "a", "demo", "sentence"], 但由于str并不能直接被神经网络所使用,所以words中的内容往往被转换为int,如[3, 10, 4, 2, 7, ...]等。多列words的情况,会被命名为words0, words1
  110. - **target**: 表示目标值。分类场景下,只有一个值;序列标注场景下是一个序列。
  111. - **seq_len**: 一般用于表示words列的长度
  112. 在中文任务中,fastNLP常用的field名称有:
  113. - **raw_words**: 如果原始汉字序列中已经包含了词语的边界,则该列称为raw_words。如"上海 浦东 开发 与 法制 建设 同步"。
  114. - **words**: 表示单独的汉字词语序列。例如["上海", "", "浦东", "开发", "与", "法制", "建设", ...]或[2, 3, 4, ...]
  115. - **raw_chars**: 表示的是原始的连续汉字序列。例如"这是一个示例。"
  116. - **chars**: 表示已经切分为单独的汉字的序列。例如["这", "是", "一", "个", "示", "例", "。"]。但由于神经网络不能识别汉字,所以一般该列会被转为int形式,如[3, 4, 5, 6, ...]。
  117. - **target**: 表示目标值。分类场景下,只有一个值;序列标注场景下是一个序列
  118. - **seq_len**: 表示输入序列的长度
  119. ----------------------------------
  120. 代码下载
  121. ----------------------------------
  122. .. raw:: html
  123. <a href="../_static/notebooks/tutorial_1_data_preprocess.ipynb" download="tutorial_1_data_preprocess.ipynb">点击下载 IPython Notebook 文件</a><hr>