zoukankan      html  css  js  c++  java
  • 自然语言推理和数据集

    自然语言推理和数据集

    Natural Language Inference and the Dataset

    情绪分析的问题。此任务旨在将单个文本序列分类为预定义的类别,例如一组情感极性。然而,当需要判断一个句子是否可以从另一个句子中推断出来,或者通过识别语义上等价的句子来消除冗余时,知道如何对一个文本序列进行分类是不够的。相反,需要能够对文本序列进行推理。

    1. Natural Language Inference

    自然语言推理研究一个假设是否可以从一个前提中推断出来,前提和前提都是文本序列。换句话说,自然语言推理决定了一对文本序列之间的逻辑关系。这种关系通常分为三类:              蕴涵:假设可以从前提中推断出来。             

    矛盾:假设的否定可以从前提推断出来。             

    中立:所有其情况。             

    自然语言推理也被称为识别文本蕴涵任务。例如,下面的一对会被标记为蕴涵,因为假设中的“示爱”可以从前提中的“拥抱”中推断出来。             

    前提:两个女人互相拥抱。             

    假设:两个女人在表达爱意。              

    下面是一个矛盾的例子,因为“运行编码示例”表示“不睡觉”而不是“睡眠”。             

    前提:一个男人正在运行一个代码示例,该示例来自于深度学习。             

    假设:这个人正在睡觉。             

    第三个例子显示了一种中立关系,因为“为演出”的事实不能推断出“著名”和“不出名”。             

    前提:音乐家在为表演。             

    假设:音乐家是有名的。             

    自然语言推理一直是理解自然语言的中心话题。在信息检索、开放领域问答等领域有着广泛的应用。为了研究这个问题,将从研究一个流行的自然语言推理基准数据集开始。

    2. The Stanford Natural Language Inference (SNLI) Dataset

    斯坦福自然语言推理(SNLI)语料库是一个50万标记英语句子对【Bowman等人,2015年】。将提取的SNLI数据集下载并存储在路径../data/SNLI_1.0中。

    import collections

    from d2l import mxnet as d2l

    from mxnet import gluon, np, npx

    import os

    import re

    import zipfile

    npx.set_np()

    #@save

    d2l.DATA_HUB['SNLI'] = (

        'https://nlp.stanford.edu/projects/snli/snli_1.0.zip',

        '9fcde07509c7e87ec61c640c1b2753d9041758e4')

    data_dir = d2l.download_extract('SNLI')

    Downloading ../data/snli_1.0.zip from https://nlp.stanford.edu/projects/snli/snli_1.0.zip...

    2.1. Reading the Dataset

    原始的SNLI数据集包含了比在实验中真正需要的更丰富的信息。因此,定义了一个函数read_snli来只提取部分数据集,然后返回前提、假设及其标签的列表。

    #@save

    def read_snli(data_dir, is_train):

        """Read the SNLI dataset into premises, hypotheses, and labels."""

        def extract_text(s):

            # Remove information that will not be used by us

            s = re.sub('\(', '', s)

            s = re.sub('\)', '', s)

            # Substitute two or more consecutive whitespace with space

            s = re.sub('\s{2,}', ' ', s)

            return s.strip()

        label_set = {'entailment': 0, 'contradiction': 1, 'neutral': 2}

        file_name = os.path.join(data_dir, 'snli_1.0_train.txt'

                                 if is_train else 'snli_1.0_test.txt')

        with open(file_name, 'r') as f:

            rows = [row.split(' ') for row in f.readlines()[1:]]

        premises = [extract_text(row[1]) for row in rows if row[0] in label_set]

        hypotheses = [extract_text(row[2]) for row in rows if row[0] in label_set]

        labels = [label_set[row[0]] for row in rows if row[0] in label_set]

        return premises, hypotheses, labels

    现在让打印第一个 3对前提和假设,以及标签(“0”、“1”和“2”分别对应于“蕴涵”、“矛盾”和“中性”)。                   

    train_data = read_snli(data_dir, is_train=True)

    for x0, x1, y in zip(train_data[0][:3], train_data[1][:3], train_data[2][:3]):

        print('premise:', x0)

        print('hypothesis:', x1)

    print('label:', y)

    premise: A person on a horse jumps over a broken down airplane .

    hypothesis: A person is training his horse for a competition .

    label: 2

    premise: A person on a horse jumps over a broken down airplane .

    hypothesis: A person is at a diner , ordering an omelette .

    label: 1

    premise: A person on a horse jumps over a broken down airplane .

    hypothesis: A person is outdoors , on a horse .

    label: 0

    test_data = read_snli(data_dir, is_train=False)

    for data in [train_data, test_data]:

        print([[row for row in data[2]].count(i) for i in range(3)])

    训练集有大约55万组,测试集有大约10000组。结果表明,在训练集和测试集中,“蕴涵”、“矛盾”和“中性”三个标签是平衡的。

    test_data = read_snli(data_dir, is_train=False)

    for data in [train_data, test_data]:

        print([[row for row in data[2]].count(i) for i in range(3)])

    [183416, 183187, 182764]

    [3368, 3237, 3219]

    2.2. Defining a Class for Loading the Dataset

    下面定义了一个类,通过继承Gluon中的dataset类来加载SNLI数据集。类构造函数中的num_steps参数指定文本序列的长度,以便每个序列的小批量都具有相同的形状。换言之,第一个num_steps后面的标记将被修剪,而特殊标记“<pad>”将被附加到较短的序列中,直到长度变为num_steps。通过实现the __getitem__ function函数,可以任意访问前提、假设和索引idx的标签。

    #@save

    class SNLIDataset(gluon.data.Dataset):

        """A customized dataset to load the SNLI dataset."""

        def __init__(self, dataset, num_steps, vocab=None):

            self.num_steps = num_steps

            all_premise_tokens = d2l.tokenize(dataset[0])

            all_hypothesis_tokens = d2l.tokenize(dataset[1])

            if vocab is None:

                self.vocab = d2l.Vocab(all_premise_tokens + all_hypothesis_tokens,

                                       min_freq=5, reserved_tokens=['<pad>'])

            else:

                self.vocab = vocab

            self.premises = self._pad(all_premise_tokens)

            self.hypotheses = self._pad(all_hypothesis_tokens)

            self.labels = np.array(dataset[2])

            print('read ' + str(len(self.premises)) + ' examples')

     

        def _pad(self, lines):

            return np.array([d2l.truncate_pad(

                self.vocab[line], self.num_steps, self.vocab['<pad>'])

                             for line in lines])

        def __getitem__(self, idx):

            return (self.premises[idx], self.hypotheses[idx]), self.labels[idx]

        def __len__(self):

            return len(self.premises)

    2.3. Putting All Things Together

    现在可以调用read_snli函数和SNLIDataset类来下载snli数据集,并返回训练集和测试集的DataLoader实例以及训练集的词汇表。值得注意的是,必须使用从测试中构建的词汇集。因此,来自测试集的任何新令牌对于训练集上训练的模型都是未知的。

    #@save

    def load_data_snli(batch_size, num_steps=50):

        """Download the SNLI dataset and return data iterators and vocabulary."""

        num_workers = d2l.get_dataloader_workers()

        data_dir = d2l.download_extract('SNLI')

        train_data = read_snli(data_dir, True)

        test_data = read_snli(data_dir, False)

        train_set = SNLIDataset(train_data, num_steps)

        test_set = SNLIDataset(test_data, num_steps, train_set.vocab)

        train_iter = gluon.data.DataLoader(train_set, batch_size, shuffle=True,

                                           num_workers=num_workers)

        test_iter = gluon.data.DataLoader(test_set, batch_size, shuffle=False,

                                          num_workers=num_workers)

        return train_iter, test_iter, train_set.vocab

    这里将批量大小设置为128,序列长度为50,并调用load_data_snli函数来获取数据迭代器和词汇表。然后打印出词汇量。

    train_iter, test_iter, vocab = load_data_snli(128, 50)

    len(vocab)

    read 549367 examples

    read 9824 examples

    18678

    现在打印第一个小批量的形状。与情绪分析相反,输入X[0]和X[1]表示一对前提和假设。

    for X, Y in train_iter:

        print(X[0].shape)

        print(X[1].shape)

        print(Y.shape)

        break

    (128, 50)

    (128, 50)

    (128,)

    3. Summary

    • Natural language inference studies whether a hypothesis can be inferred from a premise, where both are a text sequence.
    • In natural language inference, relationships between premises and hypotheses include entailment, contradiction, and neutral.
    • Stanford Natural Language Inference (SNLI) Corpus is a popular benchmark dataset of natural language inference.
  • 相关阅读:
    pytest_04
    pytest_03
    pytest_02
    CF 1416C XOR Trie
    CF 1413D
    ZOJ 3725 概率dp
    ZOJ 3726
    位运算
    CF1439C 线段树
    unordered_set
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/13228160.html
Copyright © 2011-2022 走看看