我应该如何预处理此数据集以执行“问答”任务?皮火炬

How should I preprocess this dataset for performing a "Question-Answering" task? Pytorch

提问人:evader110 提问时间:11/15/2023 最后编辑:evader110 更新时间:11/15/2023 访问量:50

问:

所以我有一个 JSON 数据集,其格式如下:

[{
    "answer": "...",
    "question": "...",
    "context": "..."
  },
 ...
]

所有字段都是普通的纯文本。我的目标是在它上面训练一个预训练的 BERT 模型,用于“问答”任务。在查看 HuggingFace 文档时,格式似乎需要与 Squad 数据集格式匹配,上下文需要修剪到最多 394 个字符,并且需要添加 [CLS] 和其他标记之类的内容。

当尝试关注文档时,我会访问此站点进行问题解答,它们提供了一个示例函数来进行预处理。为简单起见,此处提供:

def preprocess_function(examples):
    questions = [q.strip() for q in examples["question"]]
    inputs = tokenizer(
        questions,
        examples["context"],
        max_length=384,
        truncation="only_second",
        return_offsets_mapping=True,
        padding="max_length",
    )

    offset_mapping = inputs.pop("offset_mapping")
    answers = examples["answers"]
    start_positions = []
    end_positions = []

    for i, offset in enumerate(offset_mapping):
        answer = answers[i]
        start_char = answer["answer_start"][0]
        end_char = answer["answer_start"][0] + len(answer["text"][0])
        sequence_ids = inputs.sequence_ids(i)

        # Find the start and end of the context
        idx = 0
        while sequence_ids[idx] != 1:
            idx += 1
        context_start = idx
        while sequence_ids[idx] == 1:
            idx += 1
        context_end = idx - 1

        # If the answer is not fully inside the context, label it (0, 0)
        if offset[context_start][0] > end_char or offset[context_end][1] < start_char:
            start_positions.append(0)
            end_positions.append(0)
        else:
            # Otherwise it's the start and end token positions
            idx = context_start
            while idx <= context_end and offset[idx][0] <= start_char:
                idx += 1
            start_positions.append(idx - 1)

            idx = context_end
            while idx >= context_start and offset[idx][1] >= end_char:
                idx -= 1
            end_positions.append(idx + 1)

    inputs["start_positions"] = start_positions
    inputs["end_positions"] = end_positions
    return inputs

使用以下示例代码:

from transformers import AutoTokenizer
from datasets import Dataset

dataset = Dataset.from_pandas(df) # where df is a 3 column Dataframe Object | answer | question | context |

tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
tokenized_ds = dataset.map(preprocess_function, batched=True)

当我尝试运行它时,我收到以下错误。

File "c:/project.py", line 234, in preprocess_function
    inputs = tokenizer(
TypeError: 'list' object is not callable

所以我的问题是:这只是我的一个愚蠢的错误,还是我应该尝试以不同的方式预处理这个数据集?我是 HuggingFace 和 NLP 的新手,所以我把这个作为一个有趣的项目来做。提前致谢!

更新 1:更仔细地遵循教程,我将我的数据放入 Datasets 对象并正确使用了 map 函数,但现在它说分词器是一个问题,因为它与教程中使用的分词器完全相同。TypeError: 'list' object is not callable

python json pytorch huggingface-transformers 数据预处理

评论


答:

0赞 Nova 11/15/2023 #1
 from transformers import AutoTokenizer

 tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")


 questions = dataset['question'].tolist()
 contexts = dataset['context'].tolist()

 qas = preprocess_function({"question": questions, "context": contexts}, tokenizer)

评论

0赞 evader110 11/15/2023
这不起作用,因为它需要“answers”字段,即使在提供它之后,我仍然遇到了一个问题,即分词器未应用于数据集。
0赞 evader110 11/15/2023 #2

自己解决了!我的解决方案:

  1. 将 df 加载到 Datasets 对象中,以便我可以实际调用 map 函数

  2. 在预处理函数上方全局声明分词器

    感谢这个问题的帮助

  3. 更改预处理函数以匹配我的数据集。

    • answers = examples["answers"] --> answers = examples["answer"]

    • 创建contexts = examples["context"]

    • start_char = answer["answer_start"][0]

      end_char = answer["answer_start"][0] + len(answer["text"][0])

      -->

      start_char = contexts[i].find(answer)

      end_char = start_char + len(answer)