AllenNLP DatasetReader.read 返回生成器而不是 AllennlpDataset

问题描述


在学习 AllenNLP 框架(2.0.1 版)时,我尝试实现 https://guide.allennlp.org/training-and-prediction#1 中的示例代码
从 Parquet 文件中读取数据时,我得到了:
TypeError: unsupported operand type(s) for +: 'generator' and 'generator'

对于下一行:

vocab = build_vocab(train_data + dev_data)

我怀疑返回值应该是 AllennlpDataset 但也许我把它搞混了。 我做错了什么?

完整代码

train_path = <some_path>
test_path = <some_other_path>

class ClassificationJobReader(DatasetReader):
    def __init__(self,lazy: bool = False,tokenizer: Tokenizer = None,token_indexers: Dict[str,TokenIndexer] = None,max_tokens: int = None):
        super().__init__(lazy)
        self.tokenizer = tokenizer or Whitespacetokenizer()
        self.token_indexers = token_indexers or {'tokens': SingleIdTokenIndexer()}
        self.max_tokens = max_tokens

    def _read(self,file_path: str) -> Iterable[Instance]:
      df = pd.read_parquet(data_path)
      for idx in df.index:
        text = row['title'][idx] + ' ' + row['description'][idx]
        print(f'text : {text}')
        label = row['class_id'][idx]
        print(f'label : {label}')
        tokens = self.tokenizer.tokenize(text)
        if self.max_tokens:
            tokens = tokens[:self.max_tokens]
        text_field = TextField(tokens,self.token_indexers)
        label_field = LabelField(label)
        fields = {'text': text_field,'label': label_field}
        yield Instance(fields)

def build_dataset_reader() -> DatasetReader:
    return ClassificationJobReader()

def read_data(reader: DatasetReader) -> Tuple[Iterable[Instance],Iterable[Instance]]:
    print("Reading data")
    training_data = reader.read(train_path)
    validation_data = reader.read(test_path)
    return training_data,validation_data

def build_vocab(instances: Iterable[Instance]) -> Vocabulary:
    print("Building the vocabulary")
    return Vocabulary.from_instances(instances)

dataset_reader = build_dataset_reader()
train_data,dev_data = read_data(dataset_reader)
vocab = build_vocab(train_data + dev_data)

感谢您的帮助

解决方法

请先找到下面的代码修复,然后再找到解释。


代码修复

# the extend_from_instances expands your vocabulary with the instances passed as an arg
# and is therefore equivalent to Vocabulary.from_instances(train_data + dev_data) 
# previously
vocabulary.extend_from_instances(train_data)
vocabulary.extend_from_instances(dev_data)

说明

这是因为 AllenNLP API 在 allennlp==2.0.1 中有几个重大更改。您可以找到变更日志 here 和升级指南 here。根据我的理解,该指南已过时(它反映了 allennlp

DatasetReader 现在返回一个生成器,而不是以前的 List。 DatasetReader 曾经有一个名为“lazy”的参数,用于延迟加载数据。默认情况下它是 False,因此 dataset_reader.read 之前会返回一个 List。但是,从 v2.0 开始(如果我没记错的话),默认情况下会应用延迟加载,因此默认情况下它会返回一个生成器。如您所知,生成器对象的“+”运算符并未被覆盖,因此您不能简单地添加两个生成器。

因此,您可以简单地使用 vocab.extend_from_instances 来实现与以前相同的行为。希望这对你有帮助。如果您需要完整的代码片段,请在下面发表评论,我可以发布重新调整的要点并与您分享。

美好的一天!